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
use super::*;
pub fn sierra<'p, const FAC: u8, const N: usize>(
    mut image: Image<Box<[f32]>, N>,
    palette: pal<'p, N>,
) -> out<'p, pal<'p, N>> {
    let out = out::build(image.width(), image.height()).pal(palette);
    #[rustfmt::skip]
    let i = image.serpent().map(|c @ (x, y)| unsafe { 
        let p = image.pixel(x, y);
        let (_, new, i) = palette.closest(p);
        *image.pixel_mut(x, y) = new;
        let error = p.asub(new);
        let f = |f| {
            move |x: [f32; N]| {
                x.aadd(error.amul([(f as f32 / 32.) * const { FAC as f32 * (1.0 / 255.) }; N]))
            }
        };
        /*  * 5 3
        2 4 5 4 2
            2 3 2 */
        image.replace(x +             1, y, f(5));
        image.replace(x +             2, y, f(3));
        let y = y + 1;
        image.replace(x.wrapping_sub(2), y, f(2));
        image.replace(x.wrapping_sub(1), y, f(4));
        image.replace(x                , y, f(5));
        image.replace(x             + 1, y, f(4));
        image.replace(x             + 2, y, f(2));
        let y = y + 1;
        image.replace(x.wrapping_sub(1), y, f(2));
        image.replace(x                , y, f(3));
        image.replace(x             + 1, y, f(2));
        (c, i)
    });
    unsafe { out.from_iter(i) }
}

pub fn sierra_two<'p, const FAC: u8, const N: usize>(
    mut image: Image<Box<[f32]>, N>,
    palette: pal<'p, N>,
) -> out<'p, pal<'p, N>> {
    let out = out::build(image.width(), image.height()).pal(palette);
    #[rustfmt::skip]
    let i = image.serpent().map(|c@(x, y)| unsafe {
        let p = image.pixel(x, y);
        let (_, new, i) = palette.closest(p);
        *image.pixel_mut(x, y) = new;
        let error = p.asub(new);
        let f = |f| {
            move |x: [f32; N]| {
                x.aadd(error.amul([(f as f32 / 16.) * const { FAC as f32 * (1.0 / 255.) }; N]))
            }
        };
        /*  * 4 3
        1 2 3 2 1 */
        image.replace(x +             1, y, f(4));
        image.replace(x +             2, y, f(3));
        let y = y + 1;
        image.replace(x.wrapping_sub(2), y, f(1));
        image.replace(x.wrapping_sub(1), y, f(2));
        image.replace(x                , y, f(3));
        image.replace(x             + 1, y, f(2));
        image.replace(x             + 2, y, f(1));
        (c, i)
    });
    unsafe { out.from_iter(i) }
}

pub fn sierra_lite<'p, const FAC: u8, const N: usize>(
    mut image: Image<Box<[f32]>, N>,
    palette: pal<'p, N>,
) -> out<'p, pal<'p, N>> {
    let out = out::build(image.width(), image.height()).pal(palette);
    #[rustfmt::skip]
    let i = image.serpent().map(|c@(x, y)| unsafe {
        let p = image.pixel(x, y);
        let (_, new, i) = palette.closest(p);
        *image.pixel_mut(x, y) = new;
        let error = p.asub(new);
        let f = |f| {
            move |x: [f32; N]| {
                x.aadd(error.amul([(f as f32 / 4.) * const { FAC as f32 * (1.0 / 255.) }; N]))                
            }
        };
        
        #[allow(warnings)]
        /** 2
        1 1 */
        image.replace(x +             1, y, f(2));
        let y = y + 1;
        image.replace(x.wrapping_sub(1), y, f(1));
        image.replace(x                , y, f(1));
        (c, i)
    });
    unsafe { out.from_iter(i) }
}