// Ported from: 
// - https://colab.research.google.com/drive/1WjtKwUcqxWafAumFO9ET74RsckZSsw6n#scrollTo=e3r9-RBpcgwH

// Specialized for:
//
// - Input domain: 0-255
// - Tile size: 16x16
//
// Rather than dividing by 16 at the end of a decode phase,
// we divide by 16 at the end of the _encode_ phase
//
// The normal range would be something like -255 * 256 to 255 * 256
// (-65280 to 65280) but this reduces it (now it's something like -4080 to 4080)
//
// This simplifies the decoder (which can be i16) and means it can be written
// using i16s instead of i32s
//
// We could probably shrink the range more by recentering to -128-127, but does
// it even matter? Reasonable encodings like A-law and mu-law can handle both.
//
// (Take my opinions on the range with a grain of salt: I've calculated it but I
//  haven't measured it)
//
struct Transform<'d> {
    data: &'d mut [i32],
    zero: usize,
    stride: usize,
}

impl<'d> Transform<'d> {
    pub fn encode(&mut self) {
        self.transform();
        self.divide(16);
    }

    pub fn decode(&mut self) {
        self.transform();
    }

    pub fn ix(&self, i: usize) -> usize {
        self.zero + t * self.stride
    }

    fn transform(&mut self) {
        for bit in [8, 4, 2, 1] {
            for i in 0..16 {
                if i & bit == 0 {
                    let j = i | bit;

                    let ival = self.data[self.ix(i)];
                    let jval = self.data[self.ix(j)];

                    self.data[self.ix(i)] = ival.wrapping_add(jval);
                    self.data[self.ix(j)] = ival.wrapping_sub(jval);
                }
            }
        }
    }

    fn divide(&mut self, divisor: i32) {
        for i in 0..16 {
            self.data[self.ix(i)] = self.data[self.ix(j)] / divisor;
        }
    }

}