Skip to main content

av_scenechange/data/
hadamard.rs

1pub unsafe fn hadamard4x4(data: &mut [i32]) {
2    hadamard2d::<{ 4 * 4 }, 4, 4>(&mut *(data.as_mut_ptr() as *mut [i32; 16]));
3}
4
5// SAFETY: The length of data must be 64.
6pub unsafe fn hadamard8x8(data: &mut [i32]) {
7    hadamard2d::<{ 8 * 8 }, 8, 8>(&mut *(data.as_mut_ptr() as *mut [i32; 64]));
8}
9
10fn hadamard2d<const LEN: usize, const W: usize, const H: usize>(data: &mut [i32; LEN]) {
11    // Vertical transform.
12    let vert_func = if H == 4 {
13        hadamard4_1d::<LEN, W, 1, H>
14    } else {
15        hadamard8_1d::<LEN, W, 1, H>
16    };
17    vert_func(data);
18
19    // Horizontal transform.
20    let horz_func = if W == 4 {
21        hadamard4_1d::<LEN, H, W, 1>
22    } else {
23        hadamard8_1d::<LEN, H, W, 1>
24    };
25    horz_func(data);
26}
27
28#[allow(clippy::erasing_op)]
29#[allow(clippy::identity_op)]
30fn hadamard4_1d<const LEN: usize, const N: usize, const STRIDE0: usize, const STRIDE1: usize>(
31    data: &mut [i32; LEN],
32) {
33    for i in 0..N {
34        let sub: &mut [i32] = &mut data[i * STRIDE0..];
35        let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]);
36        let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]);
37        let (b0, b2) = butterfly(a0, a2);
38        let (b1, b3) = butterfly(a1, a3);
39        sub[0 * STRIDE1] = b0;
40        sub[1 * STRIDE1] = b1;
41        sub[2 * STRIDE1] = b2;
42        sub[3 * STRIDE1] = b3;
43    }
44}
45
46#[allow(clippy::erasing_op)]
47#[allow(clippy::identity_op)]
48fn hadamard8_1d<const LEN: usize, const N: usize, const STRIDE0: usize, const STRIDE1: usize>(
49    data: &mut [i32; LEN],
50) {
51    for i in 0..N {
52        let sub: &mut [i32] = &mut data[i * STRIDE0..];
53
54        let (a0, a1) = butterfly(sub[0 * STRIDE1], sub[1 * STRIDE1]);
55        let (a2, a3) = butterfly(sub[2 * STRIDE1], sub[3 * STRIDE1]);
56        let (a4, a5) = butterfly(sub[4 * STRIDE1], sub[5 * STRIDE1]);
57        let (a6, a7) = butterfly(sub[6 * STRIDE1], sub[7 * STRIDE1]);
58
59        let (b0, b2) = butterfly(a0, a2);
60        let (b1, b3) = butterfly(a1, a3);
61        let (b4, b6) = butterfly(a4, a6);
62        let (b5, b7) = butterfly(a5, a7);
63
64        let (c0, c4) = butterfly(b0, b4);
65        let (c1, c5) = butterfly(b1, b5);
66        let (c2, c6) = butterfly(b2, b6);
67        let (c3, c7) = butterfly(b3, b7);
68
69        sub[0 * STRIDE1] = c0;
70        sub[1 * STRIDE1] = c1;
71        sub[2 * STRIDE1] = c2;
72        sub[3 * STRIDE1] = c3;
73        sub[4 * STRIDE1] = c4;
74        sub[5 * STRIDE1] = c5;
75        sub[6 * STRIDE1] = c6;
76        sub[7 * STRIDE1] = c7;
77    }
78}
79
80const fn butterfly(a: i32, b: i32) -> (i32, i32) {
81    ((a + b), (a - b))
82}