RealVideo 3 and 4 decoder
authorKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 9 Jun 2018 17:29:31 +0000 (19:29 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Sat, 1 Sep 2018 09:28:39 +0000 (11:28 +0200)
Cargo.toml
src/codecs/blockdsp.rs
src/codecs/mod.rs
src/codecs/real/mod.rs [new file with mode: 0644]
src/codecs/real/rv30.rs [new file with mode: 0644]
src/codecs/real/rv3040.rs [new file with mode: 0644]
src/codecs/real/rv30dsp.rs [new file with mode: 0644]
src/codecs/real/rv34codes.rs [new file with mode: 0644]
src/codecs/real/rv34dsp.rs [new file with mode: 0644]
src/codecs/real/rv40.rs [new file with mode: 0644]
src/codecs/real/rv40dsp.rs [new file with mode: 0644]

index 8efa83882ee41495f01fe222b1911f183d02cab2..4dfbcca6c3b08978713caf1c46a3122391c41632 100644 (file)
@@ -21,7 +21,7 @@ dsp_window = ["dsp"]
 
 all_decoders = ["all_video_decoders", "all_audio_decoders"]
 
-all_video_decoders = ["decoder_clearvideo", "decoder_gdvvid", "decoder_indeo2", "decoder_indeo3", "decoder_indeo4", "decoder_indeo5", "decoder_intel263", "decoder_realvideo1", "decoder_realvideo2"]
+all_video_decoders = ["decoder_clearvideo", "decoder_gdvvid", "decoder_indeo2", "decoder_indeo3", "decoder_indeo4", "decoder_indeo5", "decoder_intel263", "decoder_realvideo1", "decoder_realvideo2", "decoder_realvideo3", "decoder_realvideo4"]
 decoder_clearvideo = ["decoders"]
 decoder_gdvvid = ["decoders"]
 decoder_indeo2 = ["decoders"]
@@ -31,6 +31,8 @@ decoder_indeo5 = ["decoders"]
 decoder_intel263 = ["h263", "decoders"]
 decoder_realvideo1 = ["h263", "decoders"]
 decoder_realvideo2 = ["h263", "decoders"]
+decoder_realvideo3 = ["decoders"]
+decoder_realvideo4 = ["decoders"]
 
 all_audio_decoders = ["decoder_pcm", "decoder_imc"]
 decoder_pcm = ["decoders"]
index 3d39a9e37783449d333a6e061cfa17a08f4e1520..af2ea13eda67e4b9ba03591b785fc4467523ccf3 100644 (file)
@@ -108,7 +108,7 @@ pub fn add_blocks(buf: &mut NAVideoBuffer<u8>, xpos: usize, ypos: usize, blk: &[
     }
 }
 
-fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) {
+pub fn edge_emu(src: &NAVideoBuffer<u8>, xpos: isize, ypos: isize, bw: usize, bh: usize, dst: &mut [u8], dstride: usize, comp: usize) {
     let stride = src.get_stride(comp);
     let offs   = src.get_offset(comp);
     let (w, h) = src.get_dimensions(comp);
index 796973c250c1c62910176a1f89b0f215ae4db8f7..185bb3d81ccbaf8185ed5b2effdc0bcb83d8a3e4 100644 (file)
@@ -235,7 +235,7 @@ pub struct DecoderInfo {
     get_decoder: fn () -> Box<NADecoder>,
 }
 
-#[cfg(feature="h263")]
+#[cfg(any(feature="h263", feature="decoder_realvideo3", feature="decoder_realvideo4"))]
 mod blockdsp;
 
 #[cfg(feature="decoder_clearvideo")]
@@ -246,6 +246,8 @@ mod gremlinvideo;
 mod indeo;
 #[cfg(feature="h263")]
 mod h263;
+#[cfg(any(feature="decoder_realvideo3", feature="decoder_realvideo4", feature="decoder_realvideo6"))]
+mod real;
 
 #[cfg(feature="decoder_pcm")]
 mod pcm;
@@ -271,6 +273,12 @@ const DECODERS: &[DecoderInfo] = &[
     DecoderInfo { name: "realvideo1", get_decoder: h263::rv10::get_decoder },
 #[cfg(feature="decoder_realvideo2")]
     DecoderInfo { name: "realvideo2", get_decoder: h263::rv20::get_decoder },
+#[cfg(feature="decoder_realvideo3")]
+    DecoderInfo { name: "realvideo3", get_decoder: real::rv30::get_decoder },
+#[cfg(feature="decoder_realvideo4")]
+    DecoderInfo { name: "realvideo4", get_decoder: real::rv40::get_decoder },
+#[cfg(feature="decoder_realvideo6")]
+    DecoderInfo { name: "realvideo6", get_decoder: real::rv60::get_decoder },
 
 #[cfg(feature="decoder_pcm")]
     DecoderInfo { name: "pcm", get_decoder: pcm::get_decoder },
diff --git a/src/codecs/real/mod.rs b/src/codecs/real/mod.rs
new file mode 100644 (file)
index 0000000..546d6b6
--- /dev/null
@@ -0,0 +1,19 @@
+#[cfg(any(feature="decoder_realvideo3", feature="decoder_realvideo4"))]
+mod rv3040;
+#[cfg(any(feature="decoder_realvideo3", feature="decoder_realvideo4"))]
+mod rv34codes;
+#[cfg(any(feature="decoder_realvideo3", feature="decoder_realvideo4"))]
+mod rv34dsp;
+
+#[cfg(feature="decoder_realvideo3")]
+pub mod rv30;
+#[cfg(feature="decoder_realvideo3")]
+pub mod rv30dsp;
+#[cfg(feature="decoder_realvideo4")]
+pub mod rv40;
+#[cfg(feature="decoder_realvideo4")]
+pub mod rv40dsp;
+#[cfg(feature="decoder_realvideo6")]
+pub mod rv60;
+
+
diff --git a/src/codecs/real/rv30.rs b/src/codecs/real/rv30.rs
new file mode 100644 (file)
index 0000000..f75b769
--- /dev/null
@@ -0,0 +1,307 @@
+use formats;
+use io::bitreader::*;
+use io::intcode::*;
+use codecs::*;
+use super::rv3040::*;
+use super::rv30dsp::*;
+
+struct RealVideo30BR {
+    rpr_bits:       u8,
+    width:          usize,
+    height:         usize,
+    widths:         Vec<usize>,
+    heights:        Vec<usize>,
+}
+
+impl RealVideo30BR {
+    fn new() -> Self {
+        RealVideo30BR {
+            rpr_bits:       0,
+            width:          0,
+            height:         0,
+            widths:         Vec::new(),
+            heights:        Vec::new(),
+        }
+    }
+}
+
+impl RV34BitstreamDecoder for RealVideo30BR {
+    fn decode_slice_header(&mut self, br: &mut BitReader, _old_w: usize, _old_h: usize) -> DecoderResult<RV34SliceHeader> {
+        if br.read(3)? != 0 { return Err(DecoderError::InvalidData); }
+        let ft_idx              = br.read(2)?;
+        let ftype = match ft_idx {
+                0|1 => FrameType::I,
+                2   => FrameType::P,
+                _   => FrameType::B,
+            };
+        if br.read(1)? != 0 { return Err(DecoderError::InvalidData); }
+        let q                   = br.read(5)? as u8;
+        let deblock             = !br.read_bool()?;
+        let pts                 = br.read(13)? as u16;
+        let rpr                 = br.read(self.rpr_bits)? as usize;
+        let (w, h) = if rpr != 0 {
+                validate!(rpr < self.widths.len());
+                (self.widths[rpr], self.heights[rpr])
+            } else {
+                (self.width, self.height)
+            };
+        let start               = br.read(get_slice_start_offset_bits(w, h))? as usize;
+                                  br.skip(1)?;
+
+        Ok(RV34SliceHeader{ ftype: ftype, quant: q, deblock: deblock, pts: pts, width: w, height: h, start: start, end: 0, set_idx: 0 })
+    }
+    fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], mut pos: usize, tstride: usize, _has_top: bool) -> DecoderResult<()> {
+        for _ in 0..4 {
+            for x in 0..2 {
+                let code = br.read_code(UintCodeType::Gamma)? as usize;
+                validate!(code < 81);
+                for k in 0..2 {
+                    let new  = RV30_ITYPE_MAP[code * 2 + k] as usize;
+                    let top  = (types[pos + x * 2 + k - tstride] + 1) as usize;
+                    let left = (types[pos + x * 2 + k - 1] + 1) as usize;
+                    types[pos + x * 2 + k] = RV30_ITYPE[top * 90 + left * 9 + new];
+                    validate!(types[pos + x * 2 + k] != 9);
+                }
+            }
+            pos += tstride;
+        }
+        Ok(())
+    }
+    fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, _mbtype: MBType) -> DecoderResult<MBInfo> {
+        let mut code = br.read_code(UintCodeType::Gamma)? as usize;
+        let mut dq = false;
+        validate!(code < 11);
+        if code > 5 {
+            code -= 6;
+            dq = true;
+        }
+        let idx = if ftype == FrameType::P { 0 } else { 1 };
+        Ok(MBInfo { mbtype: RV30_MB_TYPES[idx][code], skip_run: 0, dquant: dq })
+    }
+    fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], _mbinfo: &Vec<RV34MBInfo>) -> (MV, MV) {
+        let mb_x = sstate.mb_x;
+        let mb_y = sstate.mb_y;
+        let mv_f;
+        let mv_b;
+        match mbtype {
+            MBType::MBForward | MBType::MBBackward => {
+                    let mv_pred = mvi.pred_mb_mv(mb_x, mb_y, true, sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl);
+                    mv_f = mv_pred + mvs[0];
+                    mv_b = mv_f;
+                },
+            _   => {
+                    mv_f = ZERO_MV;
+                    mv_b = ZERO_MV;
+                },
+        };
+        (mv_f, mv_b)
+    }
+    fn quant_dc(&self, _is_intra: bool, q: u8) -> u8 { RV30_QUANT_DC[q as usize] }
+}
+
+struct RealVideo30Decoder {
+    bd:         RealVideo30BR,
+    info:       Rc<NACodecInfo>,
+    dec:        RV34Decoder,
+}
+
+impl RealVideo30Decoder {
+    fn new() -> Self {
+        RealVideo30Decoder{
+            bd:         RealVideo30BR::new(),
+            info:       Rc::new(DUMMY_CODEC_INFO),
+            dec:        RV34Decoder::new(true, Box::new(RV30DSP::new())),
+        }
+    }
+}
+
+impl NADecoder for RealVideo30Decoder {
+    fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
+        if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+            let fmt = formats::YUV420_FORMAT;
+            let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
+            self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+
+            let edata = info.get_extradata().unwrap();
+            let src: &[u8] = &edata;
+
+            if src.len() < 2 { return Err(DecoderError::InvalidData); }
+            let num_rpr     = (src[1] & 7) as usize;
+            if src.len() < num_rpr * 2 + 8 { return Err(DecoderError::ShortData); }
+            self.bd.rpr_bits  = ((num_rpr >> 1) + 1) as u8;
+            if self.bd.rpr_bits > 3 { self.bd.rpr_bits = 3; }
+            for i in 0..num_rpr+1 {
+                self.bd.widths.push ((src[6 + i * 2] as usize) << 2);
+                self.bd.heights.push((src[7 + i * 2] as usize) << 2);
+            }
+
+            self.bd.width  = vinfo.get_width();
+            self.bd.height = vinfo.get_height();
+            Ok(())
+        } else {
+println!("???");
+            Err(DecoderError::InvalidData)
+        }
+    }
+    fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+        let src = pkt.get_buffer();
+
+        let (bufinfo, ftype, pts) = self.dec.parse_frame(src.as_slice(), &mut self.bd)?;
+
+        let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+        frm.set_keyframe(ftype == FrameType::I);
+        frm.set_pts(Some(pts));
+        frm.set_frame_type(ftype);//if ftype == FrameType::B { FrameType::Skip } else { ftype } );
+        Ok(Rc::new(RefCell::new(frm)))
+    }
+}
+
+pub fn get_decoder() -> Box<NADecoder> {
+    Box::new(RealVideo30Decoder::new())
+}
+
+#[cfg(test)]
+mod test {
+    use test::dec_video::test_file_decoding;
+    #[test]
+    fn test_rv30() {
+//         test_file_decoding("realmedia", "assets/RV/rv30_chroma_drift.rm", Some(1000), true, false, /*None*/Some("rv30"));
+         test_file_decoding("realmedia", "assets/RV/rv30_weighted_mc.rm", Some(400), true, false, None/*Some("rv30")*/);
+//         test_file_decoding("realmedia", "assets/RV/simpsons-clip.rm", Some(1337)/*Some(6666)*/, true, false, /*None*/Some("rv30"));
+//panic!("end");
+    }
+}
+
+const RV30_QUANT_DC: [u8; 32] = [
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+    16, 17, 18, 19, 20, 21, 22, 22, 22, 23, 23, 23, 24, 24, 25, 25
+];
+
+const RV30_MB_TYPES: [[MBType; 6]; 2] = [
+    [ MBType::MBSkip, MBType::MBP16x16, MBType::MBP8x8,    MBType::Invalid,    MBType::MBIntra, MBType::MBIntra16 ],
+    [ MBType::MBSkip, MBType::MBDirect, MBType::MBForward, MBType::MBBackward, MBType::MBIntra, MBType::MBIntra16 ],
+];
+
+const RV30_ITYPE_MAP: [i8; 9*9*2] = [
+    0, 0, 0, 1, 1, 0, 1, 1, 0, 2, 2, 0, 0, 3, 3, 0, 1, 2,
+    2, 1, 0, 4, 4, 0, 3, 1, 1, 3, 0, 5, 5, 0, 2, 2, 1, 4,
+    4, 1, 0, 6, 3, 2, 1, 5, 2, 3, 5, 1, 6, 0, 0, 7, 4, 2,
+    2, 4, 3, 3, 6, 1, 1, 6, 7, 0, 0, 8, 5, 2, 4, 3, 2, 5,
+    3, 4, 1, 7, 4, 4, 7, 1, 8, 0, 6, 2, 3, 5, 5, 3, 2, 6,
+    1, 8, 2, 7, 7, 2, 8, 1, 5, 4, 4, 5, 3, 6, 6, 3, 8, 2,
+    4, 6, 5, 5, 6, 4, 2, 8, 7, 3, 3, 7, 6, 5, 5, 6, 7, 4,
+    4, 7, 8, 3, 3, 8, 7, 5, 8, 4, 5, 7, 4, 8, 6, 6, 7, 6,
+    5, 8, 8, 5, 6, 7, 8, 6, 7, 7, 6, 8, 8, 7, 7, 8, 8, 8,
+];
+
+const RV30_ITYPE: [i8; 10*10*9] = [
+    0, 9, 9, 9, 9, 9, 9, 9, 9,
+    0, 2, 9, 9, 9, 9, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    2, 0, 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, 9, 9, 9,
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+
+    0, 1, 9, 9, 9, 9, 9, 9, 9,
+    0, 2, 1, 6, 4, 8, 5, 7, 3,
+    1, 0, 2, 6, 5, 4, 3, 8, 7,
+    2, 8, 0, 1, 7, 4, 3, 6, 5,
+    2, 0, 1, 3, 8, 5, 4, 7, 6,
+    2, 0, 1, 4, 6, 7, 8, 3, 5,
+    0, 1, 5, 2, 6, 3, 8, 4, 7,
+    0, 1, 6, 2, 4, 7, 5, 8, 3,
+    2, 7, 0, 1, 4, 8, 6, 3, 5,
+    2, 8, 0, 1, 7, 3, 4, 5, 6,
+
+    1, 0, 9, 9, 9, 9, 9, 9, 9,
+    1, 2, 5, 6, 3, 0, 4, 8, 7,
+    1, 6, 2, 5, 3, 0, 4, 8, 7,
+    2, 1, 7, 6, 8, 3, 5, 0, 4,
+    1, 2, 5, 3, 6, 8, 4, 7, 0,
+    1, 6, 2, 0, 4, 5, 8, 7, 3,
+    1, 5, 2, 6, 3, 8, 4, 0, 7,
+    1, 6, 0, 2, 4, 5, 7, 3, 8,
+    2, 1, 7, 6, 0, 8, 5, 4, 3,
+    1, 2, 7, 8, 3, 4, 5, 6, 0,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    0, 2, 1, 8, 7, 6, 5, 4, 3,
+    1, 2, 0, 6, 5, 7, 4, 8, 3,
+    2, 8, 7, 1, 0, 6, 4, 3, 5,
+    2, 0, 8, 1, 3, 7, 5, 4, 6,
+    2, 0, 4, 1, 7, 8, 6, 3, 5,
+    2, 0, 1, 5, 8, 4, 6, 7, 3,
+    2, 0, 6, 1, 4, 7, 8, 5, 3,
+    2, 7, 8, 1, 0, 5, 4, 6, 3,
+    2, 8, 7, 1, 0, 4, 3, 6, 5,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    0, 2, 1, 3, 5, 8, 6, 4, 7,
+    1, 0, 2, 5, 3, 6, 4, 8, 7,
+    2, 8, 1, 0, 3, 5, 7, 6, 4,
+    3, 2, 5, 8, 1, 4, 6, 7, 0,
+    4, 2, 0, 6, 1, 5, 8, 3, 7,
+    5, 3, 1, 2, 8, 6, 4, 0, 7,
+    1, 6, 0, 2, 4, 5, 8, 3, 7,
+    2, 7, 0, 1, 5, 4, 8, 6, 3,
+    2, 8, 3, 5, 1, 0, 7, 6, 4,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    2, 0, 6, 1, 4, 7, 5, 8, 3,
+    1, 6, 2, 0, 4, 5, 3, 7, 8,
+    2, 8, 7, 6, 4, 0, 1, 5, 3,
+    4, 2, 1, 0, 6, 8, 3, 5, 7,
+    4, 2, 6, 0, 1, 5, 7, 8, 3,
+    1, 2, 5, 0, 6, 3, 4, 7, 8,
+    6, 4, 0, 1, 2, 7, 5, 3, 8,
+    2, 7, 4, 6, 0, 1, 8, 5, 3,
+    2, 8, 7, 4, 6, 1, 3, 5, 0,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    5, 1, 2, 3, 6, 8, 0, 4, 7,
+    1, 5, 6, 3, 2, 0, 4, 8, 7,
+    2, 1, 5, 3, 6, 8, 7, 4, 0,
+    5, 3, 1, 2, 6, 8, 4, 7, 0,
+    1, 6, 2, 4, 5, 8, 0, 3, 7,
+    5, 1, 3, 6, 2, 0, 8, 4, 7,
+    1, 6, 5, 2, 0, 4, 3, 7, 8,
+    2, 7, 1, 6, 5, 0, 8, 3, 4,
+    2, 5, 1, 3, 6, 8, 4, 0, 7,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    1, 6, 2, 0, 5, 4, 3, 7, 8,
+    1, 6, 5, 4, 2, 3, 0, 7, 8,
+    2, 1, 6, 7, 4, 8, 5, 3, 0,
+    2, 1, 6, 5, 8, 4, 3, 0, 7,
+    6, 4, 1, 2, 0, 5, 7, 8, 3,
+    1, 6, 5, 2, 3, 0, 4, 8, 7,
+    6, 1, 4, 0, 2, 7, 5, 3, 8,
+    2, 7, 4, 6, 1, 5, 0, 8, 3,
+    2, 1, 6, 8, 4, 7, 3, 5, 0,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    2, 0, 4, 7, 6, 1, 8, 5, 3,
+    6, 1, 2, 0, 4, 7, 5, 8, 3,
+    2, 7, 8, 0, 1, 6, 4, 3, 5,
+    2, 4, 0, 8, 3, 1, 7, 6, 5,
+    4, 2, 7, 0, 6, 1, 8, 5, 3,
+    2, 1, 0, 8, 5, 6, 7, 4, 3,
+    2, 6, 4, 1, 7, 0, 5, 8, 3,
+    2, 7, 4, 0, 8, 6, 1, 5, 3,
+    2, 8, 7, 4, 1, 0, 3, 6, 5,
+
+    9, 9, 9, 9, 9, 9, 9, 9, 9,
+    2, 0, 8, 1, 3, 4, 6, 5, 7,
+    1, 2, 0, 6, 8, 5, 7, 3, 4,
+    2, 8, 7, 1, 0, 3, 6, 5, 4,
+    8, 3, 2, 5, 1, 0, 4, 7, 6,
+    2, 0, 4, 8, 5, 1, 7, 6, 3,
+    2, 1, 0, 8, 5, 3, 6, 4, 7,
+    2, 1, 6, 0, 8, 4, 5, 7, 3,
+    2, 7, 8, 4, 0, 6, 1, 5, 3,
+    2, 8, 3, 0, 7, 4, 1, 6, 5,
+];
diff --git a/src/codecs/real/rv3040.rs b/src/codecs/real/rv3040.rs
new file mode 100644 (file)
index 0000000..b3ef131
--- /dev/null
@@ -0,0 +1,1321 @@
+use formats::YUV420_FORMAT;
+use frame::{NABufferType, NAVideoInfo, NAVideoBuffer, FrameType, alloc_video_buffer};
+use codecs::{MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
+use io::bitreader::{BitReader,BitReaderMode};
+use io::intcode::*;
+use std::mem;
+
+use super::rv34codes::*;
+use super::rv34dsp::*;
+
+pub struct GenericCache<T: Copy> {
+    pub height: usize,
+    pub stride: usize,
+    pub xpos:   usize,
+    pub data:   Vec<T>,
+    pub default: T,
+}
+
+impl<T:Copy> GenericCache<T> {
+    pub fn new(height: usize, stride: usize, default: T) -> Self {
+        let mut ret = Self {
+                stride: stride,
+                height: height,
+                xpos:   0,
+                data:   Vec::with_capacity((height + 1) * stride),
+                default: default,
+            };
+        ret.reset();
+        ret
+    }
+    fn full_size(&self) -> usize { self.stride * (self.height + 1) }
+    pub fn reset(&mut self) {
+        self.data.truncate(0);
+        let size = self.full_size();
+        self.data.resize(size, self.default);
+        self.xpos = self.stride + 1;
+    }
+    pub fn update_row(&mut self) {
+        for i in 0..self.stride {
+            self.data[i] = self.data[self.height * self.stride + i];
+        }
+        self.data.truncate(self.stride);
+        let size = self.full_size();
+        self.data.resize(size, self.default);
+        self.xpos = self.stride + 1;
+    }
+}
+
+trait RV34MVScale {
+    fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
+}
+
+const TR_SHIFT: u8 = 14;
+const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
+
+impl RV34MVScale for MV {
+    fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
+        let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
+        let mv_f = MV {
+                x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
+                y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
+            };
+        let mv_b = mv_f - *self;
+        (mv_f, mv_b)
+    }
+}
+
+#[derive(Clone,Copy)]
+pub struct RV34SliceHeader {
+    pub ftype:  FrameType,
+    pub quant:  u8,
+    pub pts:    u16,
+    pub width:  usize,
+    pub height: usize,
+    pub start:  usize,
+    pub end:    usize,
+    pub set_idx: usize,
+    pub deblock: bool,
+}
+
+impl RV34SliceHeader {
+    pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
+        (self.ftype  == cmp.ftype)  &&
+        (self.pts    == cmp.pts)    &&
+        (self.width  == cmp.width)  &&
+        (self.height == cmp.height)
+    }
+}
+
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy,PartialEq)]
+pub enum MBType {
+    MBIntra,
+    MBIntra16,
+    MBSkip,
+    MBP16x16,
+    MBP16x16Mix,
+    MBP16x8,
+    MBP8x16,
+    MBP8x8,
+    MBDirect,
+    MBBidir,
+    MBForward,
+    MBBackward,
+    Invalid,
+}
+
+impl MBType {
+    pub fn is_intra(&self) -> bool {
+        (*self == MBType::MBIntra) || (*self == MBType::MBIntra16)
+    }
+    pub fn is_16(&self) -> bool {
+        (*self == MBType::MBIntra16) || (*self == MBType::MBP16x16Mix)
+    }
+    pub fn is_intra_or_16(&self) -> bool {
+        self.is_intra() || self.is_16()
+    }
+    pub fn get_num_mvs(&self) -> usize {
+        match *self {
+            MBType::MBIntra | MBType::MBIntra16 |
+            MBType::MBSkip | MBType::MBDirect                       => 0,
+            MBType::MBP16x16 | MBType::MBP16x16Mix |
+            MBType::MBForward | MBType::MBBackward                  => 1,
+            MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir     => 2,
+            MBType::MBP8x8                                          => 4,
+            MBType::Invalid => unreachable!(),
+        }
+    }
+    pub fn is_fwd(&self) -> bool {
+        match *self {
+            MBType::MBP16x16 | MBType::MBP16x16Mix |
+            MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
+            MBType::MBForward => true,
+            _ => false,
+        }
+    }
+    pub fn is_bwd(&self) -> bool {
+        match *self {
+            MBType::MBBidir | MBType::MBBackward => true,
+            _                  => false,
+        }
+    }
+    pub fn has_mv_dir(&self, fwd: bool) -> bool {
+        match *self {
+            MBType::MBBidir             => true,
+            MBType::MBForward  if  fwd  => true,
+            MBType::MBBackward if !fwd  => true,
+            _ => false,
+        }
+    }
+    pub fn is_nomv(&self) -> bool {
+        match *self {
+            MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
+            _                  => false,
+        }
+    }
+    /*pub fn is_16x16(&self) -> bool {
+        match *self {
+            MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
+            _ => true,
+        }
+    }*/
+    fn get_weight(&self) -> usize {
+        match *self {
+            MBType::MBIntra     => 0,
+            MBType::MBIntra16   => 1,
+            MBType::MBSkip      => unreachable!(),
+            MBType::MBP16x16    => 2,
+            MBType::MBP16x16Mix => 10,
+            MBType::MBP16x8     => 7,
+            MBType::MBP8x16     => 8,
+            MBType::MBP8x8      => 3,
+            MBType::MBDirect    => 6,
+            MBType::MBBidir     => 9,
+            MBType::MBForward   => 4,
+            MBType::MBBackward  => 5,
+            MBType::Invalid     => unreachable!(),
+        }
+    }
+}
+
+const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
+    MBType::MBIntra,    MBType::MBIntra16,  MBType::MBP16x16,   MBType::MBP8x8,
+    MBType::MBForward,  MBType::MBBackward, MBType::MBDirect,   MBType::MBP16x8,
+    MBType::MBP8x16,    MBType::MBBidir,    MBType::MBP16x16Mix,
+];
+
+#[derive(Clone,Copy)]
+pub struct MBInfo {
+    pub mbtype:     MBType,
+    pub skip_run:   usize,
+    pub dquant:     bool,
+}
+
+#[derive(Clone,Copy)]
+pub struct RV34MBInfo {
+    pub mbtype: MBType,
+    pub cbp:    u32,
+    pub deblock:u16,
+    pub cbp_c:  u8, // for deblocking purposes
+    pub q:      u8,
+}
+
+struct IntraModeState {
+    cache:  GenericCache<i8>,
+}
+
+const RV34_INTRA_PRED4: [PredType4x4; 9] = [
+    PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
+    PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
+    PredType4x4::VerRight, PredType4x4::VerLeft,
+    PredType4x4::HorUp, PredType4x4::HorDown
+];
+
+const RV34_INTRA_PRED16: [PredType8x8; 4] = [
+    PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
+];
+
+impl IntraModeState {
+    fn new(mb_w: usize) -> Self {
+        let stride = 1 + mb_w * 4 + 1;
+        IntraModeState { cache: GenericCache::new(4, stride, -1) }
+    }
+    fn reset(&mut self) { self.cache.reset(); }
+    fn update(&mut self) { self.cache.update_row(); }
+    fn get_pos(&self, xpos: usize) -> usize {
+        self.cache.stride + 1 + xpos * 4
+    }
+    fn set_mb_x(&mut self, mb_x: usize) {
+        self.cache.xpos = self.get_pos(mb_x);
+    }
+    fn fill_block(&mut self, val: i8) {
+        let mut pos = self.cache.xpos;
+        for _ in 0..4 {
+            for j in 0..4 {
+                self.cache.data[pos + j] = val;
+            }
+            pos += self.cache.stride;
+        }
+    }
+    fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
+        if !has_top && !has_left { return PredType8x8::DC128; }
+        let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
+        if !has_top {
+            im = match im {
+                    PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
+                    PredType8x8::DC => PredType8x8::LeftDC,
+                    _   => im,
+                 };
+        } else if !has_left {
+            im = match im {
+                    PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
+                    PredType8x8::DC => PredType8x8::TopDC,
+                    _   => im,
+                 };
+        }
+        im
+    }
+    fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
+        if !has_top && !has_left { return PredType8x8::DC128; }
+        let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
+        im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
+        if !has_top {
+            im = match im {
+                    PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
+                    PredType8x8::DC => PredType8x8::LeftDC,
+                    _   => im,
+                 };
+        } else if !has_left {
+            im = match im {
+                    PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
+                    PredType8x8::DC => PredType8x8::TopDC,
+                    _   => im,
+                 };
+        }
+        im
+    }
+    fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
+        let no_up = !has_top && (y == 0);
+        let no_left = !has_left && (x == 0);
+        if no_up && no_left { return PredType4x4::DC128; }
+        let no_down = !has_left || (x != 0) || (y == 3);
+
+//println!("      orig {} @ {}", self.cache.data[self.cache.xpos + x + y * self.cache.stride], self.cache.xpos + x + y * self.cache.stride);
+        let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
+
+        if no_up {
+            im = match im {
+                    PredType4x4::Ver => PredType4x4::Hor,
+                    PredType4x4::DC  => PredType4x4::LeftDC,
+                    _                => im,
+                 };
+        } else if no_left {
+            im = match im {
+                    PredType4x4::Hor            => PredType4x4::Ver,
+                    PredType4x4::DC             => PredType4x4::TopDC,
+                    PredType4x4::DiagDownLeft   => PredType4x4::DiagDownLeftNoDown,
+                    _                           => im,
+                 };
+        }
+        if no_down {
+            im = match im {
+                    PredType4x4::DiagDownLeft   => PredType4x4::DiagDownLeftNoDown,
+                    PredType4x4::HorUp          => PredType4x4::HorUpNoDown,
+                    PredType4x4::VerLeft        => PredType4x4::VerLeftNoDown,
+                    _                           => im,
+                 };
+        }
+        im
+    }
+    //todo merge
+    fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
+        let no_up = !has_top && (y == 0);
+        let no_left = !has_left && (x == 0);
+        if no_up && no_left { return PredType4x4::DC128; }
+        let no_down = !has_left || (x != 0) || (y == 1);
+
+//println!("      orig {}", self.cache.data[self.cache.xpos + x + y * self.cache.stride]);
+        let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
+
+        if no_up {
+            im = match im {
+                    PredType4x4::Ver => PredType4x4::Hor,
+                    PredType4x4::DC  => PredType4x4::LeftDC,
+                    _                => im,
+                 };
+        } else if no_left {
+            im = match im {
+                    PredType4x4::Hor            => PredType4x4::Ver,
+                    PredType4x4::DC             => PredType4x4::TopDC,
+                    PredType4x4::DiagDownLeft   => PredType4x4::DiagDownLeftNoDown,
+                    _                           => im,
+                 };
+        }
+        if no_down {
+            im = match im {
+                    PredType4x4::DiagDownLeft   => PredType4x4::DiagDownLeftNoDown,
+                    PredType4x4::HorUp          => PredType4x4::HorUpNoDown,
+                    PredType4x4::VerLeft        => PredType4x4::VerLeftNoDown,
+                    _                           => im,
+                 };
+        }
+        im
+    }
+}
+
+pub struct MVInfo {
+    pub mv_b:   Vec<MV>,
+    pub mv_f:   Vec<MV>,
+    pub w:      usize,
+    pub h:      usize,
+    pub has_b:  Vec<bool>,
+    pub has_f:  Vec<bool>,
+}
+
+impl MVInfo {
+    fn new() -> Self {
+        Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
+    }
+    fn resize(&mut self, mb_w: usize, mb_h: usize) {
+        self.w = mb_w * 2;
+        self.h = mb_h * 2;
+        self.reset();
+    }
+    fn reset(&mut self) {
+        let size = self.w * self.h;
+        self.mv_f.truncate(0);
+        self.mv_f.resize(size, ZERO_MV);
+        self.mv_b.truncate(0);
+        self.mv_b.resize(size, ZERO_MV);
+        self.has_f.truncate(0);
+        self.has_f.resize(size >> 2, false);
+        self.has_b.truncate(0);
+        self.has_b.resize(size >> 2, false);
+    }
+    fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
+        let idx = mb_x * 2 + mb_y * 2 * self.w;
+        if fwd {
+            self.mv_f[idx          + 0] = mv;
+            self.mv_f[idx          + 1] = mv;
+            self.mv_f[idx + self.w + 0] = mv;
+            self.mv_f[idx + self.w + 1] = mv;
+        } else {
+            self.mv_b[idx          + 0] = mv;
+            self.mv_b[idx          + 1] = mv;
+            self.mv_b[idx + self.w + 0] = mv;
+            self.mv_b[idx + self.w + 1] = mv;
+        }
+    }
+    fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
+        if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
+    }
+    fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
+        if !has_top && !has_left { return ZERO_MV; }
+        let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
+        let top_mv  = if has_top  { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
+        let tr_add = if is16 { 2 } else { 1 };
+        let tr_mv;
+        if has_tr {
+            tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
+        } else if has_tl {
+            tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
+        } else {
+            tr_mv = left_mv;
+        }
+//print!("      pred {}  {}  {}", left_mv, top_mv, tr_mv);
+        MV::pred(left_mv, top_mv, tr_mv)
+    }
+    pub fn pred_mb_mv(&self, mb_x: usize, mb_y: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool) -> MV {
+        self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
+    }
+    fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
+        let mb_idx = mb_x + mb_y * (self.w >> 1);
+        self.has_f[mb_idx] = mbtype.is_fwd();
+        self.has_b[mb_idx] = mbtype.is_bwd();
+        if mbtype.is_nomv() {
+            self.fill(mb_x, mb_y, true,  ZERO_MV);
+            self.fill(mb_x, mb_y, false, ZERO_MV);
+            return;
+        }
+//println!("     mvpred {:?} - {}", mbtype, mbtype.is_16x16());
+//for i in 0..mbtype.get_num_mvs() { println!("       {}", mvs[i]);}
+        if mbtype.is_fwd() {
+            self.fill(mb_x, mb_y, false, ZERO_MV);
+        } else if mbtype.is_bwd() {
+            self.fill(mb_x, mb_y, true, ZERO_MV);
+        }
+        let idx = mb_x * 2 + mb_y * 2 * self.w;
+/*        let pred_mv = if mbtype.is_16x16() && mbtype != MBType::MBSkip {
+                self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true)
+            } else {
+                ZERO_MV
+            };*/
+
+        match mbtype {
+            MBType::MBSkip => {
+                    self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
+                },
+            MBType::MBP16x16 |
+            MBType::MBP16x16Mix => {
+let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
+//println!(" + {}", mvs[0]);
+                    let new_mv = mvs[0] + pred_mv;
+                    self.fill(mb_x, mb_y, true, new_mv);
+                },
+            MBType::MBP16x8 => {
+let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
+//println!(" + {}", mvs[0]);
+                    let new_mv = mvs[0] + pred_mv;
+                    self.mv_f[idx + 0] = new_mv;
+                    self.mv_f[idx + 1] = new_mv;
+
+                    let idx2 = idx + self.w;
+                    let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
+//println!(" + {}", mvs[1]);
+                    let new_mv = mvs[1] + pred_mv;
+                    self.mv_f[idx2 + 0] = new_mv;
+                    self.mv_f[idx2 + 1] = new_mv;
+                },
+            MBType::MBP8x16 => {
+                    let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
+//println!(" + {}", mvs[0]);
+                    let new_mv = mvs[0] + pred_mv;
+                    self.mv_f[idx]          = new_mv;
+                    self.mv_f[idx + self.w] = new_mv;
+
+                    let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
+//println!(" + {}", mvs[1]);
+                    let new_mv = mvs[1] + pred_mv;
+                    self.mv_f[idx          + 1] = new_mv;
+                    self.mv_f[idx + self.w + 1] = new_mv;
+                },
+            MBType::MBP8x8 => {
+                    let mut idx8 = idx;
+                    let mut has_top = sstate.has_top;
+                    for y in 0..2 {
+                        for x in 0..2 {
+                            let has_left = (x > 0) || sstate.has_left;
+                            let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
+                            let has_tl;
+                            if y == 0 {
+                                has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
+                            } else {
+                                has_tl = if x == 0 { sstate.has_left } else { true };
+                            }
+                            let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
+//println!(" + {}", mvs[x+y*2]);
+                            let new_mv = mvs[x + y * 2] + pred_mv;
+                            self.mv_f[idx8 + x] = new_mv;
+                        }
+                        has_top = true;
+                        idx8 += self.w;
+                    }
+                },
+            MBType::MBDirect => {
+                    let mut cum_mv_f = ZERO_MV;
+                    let mut cum_mv_b = ZERO_MV;
+                    let mut idx8 = idx;
+                    for _ in 0..2 {
+                        for x in 0..2 {
+                            let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
+                            cum_mv_f += mv_f;
+                            cum_mv_b += mv_b;
+                        }
+                        idx8 += self.w;
+                    }
+                    cum_mv_f.x >>= 2;
+                    cum_mv_f.y >>= 2;
+                    cum_mv_b.x >>= 2;
+                    cum_mv_b.y >>= 2;
+                    self.fill(mb_x, mb_y, true,  cum_mv_f);
+                    self.fill(mb_x, mb_y, false, cum_mv_b);
+                },
+            MBType::MBBidir => {
+                    let pred_mv_f = ZERO_MV;
+                    let new_mv = pred_mv_f + mvs[0];
+                    self.fill(mb_x, mb_y, true,  new_mv);
+                    let pred_mv_b = ZERO_MV;
+                    let new_mv = pred_mv_b + mvs[1];
+                    self.fill(mb_x, mb_y, false, new_mv);
+                },
+            MBType::MBForward => {
+let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
+println!("    fwd = {} + {}", pred_mv, mvs[0]);
+                    let new_mv = mvs[0] + pred_mv;
+                    self.fill(mb_x, mb_y, true,  new_mv);
+                },
+            MBType::MBBackward => {
+let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
+println!("    bwd = {} + {}", pred_mv, mvs[0]);
+                    let new_mv = mvs[0] + pred_mv;
+                    self.fill(mb_x, mb_y, false, new_mv);
+                },
+            _ => {},
+        }
+    }
+    pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
+        let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
+        if fwd { self.mv_f[idx] }
+        else   { self.mv_b[idx] }
+    }
+    fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
+        let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
+        let off = if vert { self.w } else { 1 };
+        let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
+        let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
+        (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
+    }
+}
+
+pub trait RV34BitstreamDecoder {
+    fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
+    fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
+    fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
+    fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
+    fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &Vec<RV34MBInfo>) -> (MV, MV);
+}
+
+pub trait RV34DSP {
+    fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize);
+    fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
+    fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool);
+}
+
+fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
+    let num_slices = (src[0] as usize) + 1;
+    let ini_off = num_slices * 8 + 1;
+    offsets.truncate(0);
+
+    if ini_off >= src.len() { return Err(DecoderError::ShortData); }
+
+    let mut br = BitReader::new(&src[1..], ini_off - 1, BitReaderMode::BE);
+
+    for i in 0..num_slices {
+        br.skip(32)?;
+        let off = br.read(32)? as usize;
+        if (i == 0) && (off != 0) {
+            return Err(DecoderError::InvalidData);
+        }
+        if (i > 0) && (off <= offsets[i - 1]) {
+            return Err(DecoderError::InvalidData);
+        }
+        offsets.push(off);
+    }
+
+    Ok(())
+}
+
+fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &Vec<usize>, old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
+    validate!(slice_no < slice_offs.len());
+    br.seek((slice_offs[slice_no] * 8) as u32)?;
+    let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
+    if slice_no < slice_offs.len() - 1 {
+        let cur_pos = br.tell() as u32;
+        br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
+        let nhdr = bd.decode_slice_header(br, shdr.width, shdr.height)?;
+        br.seek(cur_pos)?;
+        validate!(nhdr.start > shdr.start);
+        shdr.end = nhdr.start;
+    } else {
+        shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
+    }
+//println!(" slice {}: {} - {}x{} deblock {} {:X} q{} {}-{}", slice_no, shdr.ftype, shdr.width, shdr.height, shdr.deblock, shdr.pts, shdr.quant, shdr.start, shdr.end);
+    Ok(shdr)
+}
+
+const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
+const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
+
+pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
+    let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
+    let mut idx: usize = 0;
+    while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
+    RV34_SLICE_START_BITS[idx]
+}
+
+const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
+    [  0, 0 ], [  2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
+    [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
+    [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
+    [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
+];
+
+const RV34_QUANT_TAB: [u16; 32] = [
+     60,   67,   76,   85,   96,  108,  121,  136,
+    152,  171,  192,  216,  242,  272,  305,  341,
+    383,  432,  481,  544,  606,  683,  767,  854,
+    963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
+];
+
+const RV34_CHROMA_QUANT_DC: [u8; 32] = [
+     0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+    14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
+];
+const RV34_CHROMA_QUANT_AC: [u8; 32] = [
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+    16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
+];
+
+fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
+    if br.read_bool()? {
+        let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
+        let qp = (q as i8) + diff;
+        validate!((qp > 0) && (qp < 32));
+        Ok(qp as u8)
+    } else {
+        let qp = br.read(5)? as u8;
+        Ok(qp)
+    }
+}
+
+pub struct SState {
+    pub mb_x:       usize,
+    pub mb_y:       usize,
+    pub mb_w:       usize,
+    pub mb_h:       usize,
+    pub cbp:        u32,
+    pub q:          u8,
+    pub q_dc:       u8,
+    pub set_idx:    usize,
+    pub has_left:   bool,
+    pub has_top:    bool,
+    pub has_tl:     bool,
+    pub has_tr:     bool,
+    pub trd:        u16,
+    pub trb:        u16,
+}
+
+impl SState {
+    fn new() -> Self {
+        Self {
+            mb_x:       0,
+            mb_y:       0,
+            mb_w:       0,
+            mb_h:       0,
+            cbp:        0,
+            q:          0,
+            q_dc:       0,
+            set_idx:    0,
+            has_left:   false,
+            has_top:    false,
+            has_tl:     false,
+            has_tr:     false,
+            trd:        0,
+            trb:        0,
+        }
+    }
+}
+
+struct MBHist {
+    is_p:   bool,
+    hist:   [MBType; 4],
+    count:  usize,
+}
+
+impl MBHist {
+    fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
+    fn add(&mut self, mbt: MBType) {
+        let mbt2 = match mbt {
+                MBType::MBSkip if  self.is_p => MBType::MBP16x16,
+                MBType::MBSkip if !self.is_p => MBType::MBDirect,
+                _ => mbt,
+            };
+        self.hist[self.count] = mbt2;
+        self.count += 1;
+    }
+    fn get_mbtype(&self) -> MBType {
+        if self.count == 0 {
+            MBType::MBIntra
+        } else if self.count == 1 {
+            self.hist[0]
+        } else if self.count == 2 {
+            if self.hist[0].get_weight() <= self.hist[1].get_weight() {
+                self.hist[0]
+            } else {
+                self.hist[1]
+            }
+        } else {
+            let mut w: [usize; 12] = [0; 12];
+            for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
+            let mut nz_idx = 0;
+            for i in 0..12 {
+                if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
+                if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
+            }
+
+            MBTYPE_FROM_WEIGHT[nz_idx]
+        }
+    }
+}
+
+fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
+    let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
+    let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
+    Ok(MV{ x: x, y: y })
+}
+
+fn do_mc_16x16(dsp: &Box<RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
+    dsp.do_luma_mc  (buf, prevbuf, mb_x * 16, mb_y * 16,    mv, true, avg);
+    dsp.do_chroma_mc(buf, prevbuf, mb_x *  8, mb_y *  8, 1, mv, true, avg);
+    dsp.do_chroma_mc(buf, prevbuf, mb_x *  8, mb_y *  8, 2, mv, true, avg);
+}
+
+fn do_mc_8x8(dsp: &Box<RV34DSP>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
+    dsp.do_luma_mc  (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8,    mv, false, avg);
+    dsp.do_chroma_mc(buf, prevbuf, mb_x *  8 + xoff * 4, mb_y *  8 + yoff * 4, 1, mv, false, avg);
+    dsp.do_chroma_mc(buf, prevbuf, mb_x *  8 + xoff * 4, mb_y *  8 + yoff * 4, 2, mv, false, avg);
+}
+
+fn do_avg(cdsp: &RV34CommonDSP, buf: &mut NAVideoBuffer<u8>, avg_buf: &NAVideoBuffer<u8>, mb_x: usize, xb: usize, mb_y: usize, yb: usize, size: usize, ratio1: u32, ratio2: u32) {
+    for comp in 0..3 {
+        let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
+        let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
+        let csize = if comp == 0 { size } else { size >> 1 };
+        let dstride = buf.get_stride(comp);
+        let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
+        let mut data = buf.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let sstride = avg_buf.get_stride(comp);
+        let soffset = avg_buf.get_offset(comp);
+        let data = avg_buf.get_data();
+        let src: &[u8] = data.as_slice();
+
+        if ratio1 == ratio2 {
+            cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
+        } else {
+            cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
+        }
+    }
+}
+
+pub struct RV34Decoder {
+    is_rv30:    bool,
+    coderead:   RV34Codes,
+    dsp:        Box<RV34DSP>,
+    cdsp:       RV34CommonDSP,
+    width:      usize,
+    height:     usize,
+    ipbs:       IPBShuffler,
+    mvi:        MVInfo,
+    ref_mvi:    MVInfo,
+    last_ts:    u16,
+    next_ts:    u16,
+    ratio1:     u32,
+    ratio2:     u32,
+    is_b:       bool,
+    mbinfo:     Vec<RV34MBInfo>,
+    avg_buf:    NAVideoBuffer<u8>,
+    base_ts:    u64,
+}
+
+impl RV34Decoder {
+    pub fn new(is_rv30: bool, dsp: Box<RV34DSP>) -> Self {
+        let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
+        let mut vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
+        let vb = vt.get_vbuf();
+        let avg_buf = vb.unwrap();
+        RV34Decoder {
+            is_rv30:    is_rv30,
+            coderead:   RV34Codes::new(),
+            dsp:        dsp,
+            cdsp:       RV34CommonDSP::new(),
+            ipbs:       IPBShuffler::new(),
+            mvi:        MVInfo::new(),
+            ref_mvi:    MVInfo::new(),
+            mbinfo:     Vec::new(),
+            width: 0, height: 0,
+            last_ts: 0, next_ts: 0,
+            ratio1: 0, ratio2: 0,
+            is_b:       false,
+            avg_buf:    avg_buf,
+            base_ts:    0,
+        }
+    }
+    fn decode_mb_header_intra(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
+        if is_i16 {
+            let imode = br.read(2)? as i8;
+            im.fill_block(imode);
+            return Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false });
+        } else {
+            let dq = if !has_dq {
+                    if !self.is_rv30 { !br.read_bool()? } else { false }
+                } else { false };
+            if dq {
+                decode_dquant(br, q)?;
+            }
+            bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
+            return Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq });
+        }
+    }
+    fn decode_mb_header_inter(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
+        let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
+        validate!(hdr.mbtype != MBType::Invalid);
+        if hdr.dquant {
+            decode_dquant(br, q)?;
+        }
+        if hdr.mbtype.is_intra() {
+            return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
+        }
+        return Ok(hdr);
+    }
+
+    fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
+        let mut cur_cbp = sstate.cbp;
+        {
+            let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
+            let q_ac = RV34_QUANT_TAB[sstate.q as usize];
+            let luma_set = if is_16 { 2 } else { 1 };
+            let mut coeffs16: [i16; 16] = [0; 16];
+            if is_16 {
+                let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
+                if has_ac {
+                    self.cdsp.transform16(&mut coeffs16);
+                } else {
+                    self.cdsp.transform16_dc(&mut coeffs16);
+                }
+            }
+            let stride = buf.get_stride(0);
+            let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
+            let mut data = buf.get_data_mut();
+            let framebuf: &mut [u8] = data.as_mut_slice();
+
+            if is_16 {
+                let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
+//println!("     pred16 {:?}", im16);
+                self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
+            }
+
+            for y in 0..4 {
+                for x in 0..4 {
+                    let mut coeffs: [i16; 16] = [0; 16];
+                    let has_ac;
+                    if (cur_cbp & 1) != 0 {
+                        has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
+                    } else {
+                        has_ac = false;
+                    }
+                    if is_16 {
+                        coeffs[0] = coeffs16[x + y * 4];
+                    } else {
+                        let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
+                        let has_top = sstate.has_top || (y > 0);
+                        let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
+                        let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
+                                let i = offset + x * 4 - stride;
+                                [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
+                            } else if has_top {
+                                let i = offset + x * 4 - stride;
+                                [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
+                            } else {
+                                [0; 4]
+                            };
+//println!("    pred4 {},{} {:?} ({})", x, y, im, im as u8);
+                        self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
+                    }
+                    if has_ac {
+                        self.cdsp.transform(&mut coeffs);
+                    } else {
+                        self.cdsp.transform_dc(&mut coeffs);
+                    }
+                    self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
+                    cur_cbp >>= 1;
+                }
+                offset += stride * 4;
+            }
+        }
+        let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
+        let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
+        let chroma_set = 0;
+        for comp in 1..3 {
+            let stride = buf.get_stride(comp);
+            let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
+            let mut data = buf.get_data_mut();
+            let framebuf: &mut [u8] = data.as_mut_slice();
+            if is_16 {
+                let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
+//println!("     pred8 {:?}", im8);
+                self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
+            }
+            for y in 0..2 {
+                for x in 0..2 {
+                    let mut coeffs: [i16; 16] = [0; 16];
+                    let has_ac;
+                    if (cur_cbp & 1) != 0 {
+                        has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
+                    } else {
+                        has_ac = false;
+                    }
+                    if !is_16 {
+                        let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
+                        let has_top = sstate.has_top || (y > 0);
+                        let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
+                        let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
+                                let i = offset + x * 4 - stride;
+                                [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
+                            } else if has_top {
+                                let i = offset + x * 4 - stride;
+                                [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
+                            } else {
+                                [0; 4]
+                            };
+//println!("    pred4chr {},{} {:?} ({})", x, y, im, im as u8);
+                        self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
+                    }
+                    if has_ac {
+                        self.cdsp.transform(&mut coeffs);
+                    } else {
+                        self.cdsp.transform_dc(&mut coeffs);
+                    }
+                    self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
+                    cur_cbp >>= 1;
+                }
+                offset += stride * 4;
+            }
+        }
+        Ok(())
+    }
+
+    fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
+        let mb_x = sstate.mb_x;
+        let mb_y = sstate.mb_y;
+        match mbh.mbtype {
+            MBType::MBP16x16 | MBType::MBP16x16Mix => {
+                    if let Some(ref prevbuf) = self.ipbs.get_lastref() {
+                        let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
+                        do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
+                    }
+                },
+            MBType::MBForward => {
+                    if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
+                        let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
+                        do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
+                    }
+                },
+            MBType::MBBackward => {
+                    if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
+                        let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
+                        do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
+                    }
+                },
+            MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
+                    if let Some(ref prevbuf) = self.ipbs.get_lastref() {
+                        for y in 0..2 {
+                            for x in 0..2 {
+                                let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
+                                do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
+                            }
+                        }
+                    }
+                },
+            MBType::MBSkip if !self.is_b => {
+                    if let Some(ref prevbuf) = self.ipbs.get_lastref() {
+                        do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
+                    }
+                },
+            MBType::MBSkip | MBType::MBDirect => {
+                    if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
+                        for y in 0..2 {
+                            for x in 0..2 { 
+                                let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
+                                do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
+                                do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
+                                do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
+                            }
+                        }
+                    }
+                },
+            MBType::MBBidir => {
+                    if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
+                        let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
+                        let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
+                        do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
+                        do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
+                        do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
+                    }
+                },
+            _ => {},
+        };
+    }
+    fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
+        self.do_mc(buf, mbh, sstate);
+
+        let mut cur_cbp = sstate.cbp;
+
+        {
+            let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
+            let q_ac = RV34_QUANT_TAB[sstate.q as usize];
+            let luma_set = if is_16 { 2 } else { 0 };
+            let mut coeffs16: [i16; 16] = [0; 16];
+            if is_16 {
+                let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
+                if has_ac {
+                    self.cdsp.transform16(&mut coeffs16);
+                } else {
+                    self.cdsp.transform16_dc(&mut coeffs16);
+                }
+            }
+            let stride = buf.get_stride(0);
+            let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
+            let mut data = buf.get_data_mut();
+            let framebuf: &mut [u8] = data.as_mut_slice();
+
+            for y in 0..4 {
+                for x in 0..4 {
+                    let mut coeffs: [i16; 16] = [0; 16];
+                    let has_ac;
+                    if (cur_cbp & 1) != 0 {
+                        has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
+                    } else {
+                        has_ac = false;
+                    }
+                    if is_16 {
+                        coeffs[0] = coeffs16[x + y * 4];
+                    }
+                    if has_ac {
+                        self.cdsp.transform(&mut coeffs);
+                    } else {
+                        self.cdsp.transform_dc(&mut coeffs);
+                    }
+                    self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
+                    cur_cbp >>= 1;
+                }
+                offset += stride * 4;
+            }
+        }
+        if is_16 {
+            self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
+        }
+        let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
+        let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
+        let chroma_set = 1;
+        for comp in 1..3 {
+            let stride = buf.get_stride(comp);
+            let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
+            let mut data = buf.get_data_mut();
+            let framebuf: &mut [u8] = data.as_mut_slice();
+            for _ in 0..2 {
+                for x in 0..2 {
+                    let mut coeffs: [i16; 16] = [0; 16];
+                    let has_ac;
+                    if (cur_cbp & 1) != 0 {
+                        has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
+                    } else {
+                        has_ac = false;
+                    }
+                    if has_ac {
+                        self.cdsp.transform(&mut coeffs);
+                    } else {
+                        self.cdsp.transform_dc(&mut coeffs);
+                    }
+                    self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
+                    cur_cbp >>= 1;
+                }
+                offset += stride * 4;
+            }
+        }
+        Ok(())
+    }
+    fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut Vec<RV34MBInfo>) {
+        let mbt = mbinfo[mb_pos].mbtype;
+        let mut hmvmask = 0;
+        let mut vmvmask = 0;
+
+        for y in 0..2 {
+            for x in 0..2 {
+                let shift = x * 2 + y * 8;
+                if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
+                    vmvmask |= 0x11 << shift;
+                }
+                if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
+                    hmvmask |= 0x03 << shift;
+                }
+            }
+        }
+        if !sstate.has_top  { hmvmask &= !0x000F; }
+        if sstate.mb_x == 0 { vmvmask &= !0x1111; }
+        if self.is_rv30 {
+            vmvmask |= (vmvmask & 0x4444) >> 1;
+            hmvmask |= (hmvmask & 0x0F00) >> 4;
+            if sstate.mb_x > 0 {
+                mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
+            }
+            if sstate.has_top {
+
+                mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
+            }
+        }
+        if mbt.is_intra_or_16() {
+            mbinfo[mb_pos].deblock = 0xFFFF;
+            mbinfo[mb_pos].cbp_c   = 0xFF;
+        } else {
+            mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
+            mbinfo[mb_pos].cbp_c   = (mbinfo[mb_pos].cbp >> 16) as u8;
+        }
+    }
+
+    pub fn parse_frame(&mut self, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
+        let mut slice_offs: Vec<usize> = Vec::new();
+        parse_slice_offsets(src, &mut slice_offs)?;
+        let ini_off = slice_offs.len() * 8 + 1;
+
+        let mut br = BitReader::new(&src[ini_off..], src.len() - ini_off, BitReaderMode::BE);
+        let hdr0 = decode_slice_header(&mut br, bd, 0, &slice_offs, self.width, self.height)?;
+        validate!((hdr0.width != 0) && (hdr0.height != 0));
+        self.width  = hdr0.width;
+        self.height = hdr0.height;
+        let mb_w = (hdr0.width  + 15) >> 4;
+        let mb_h = (hdr0.height + 15) >> 4;
+        let mut mb_pos: usize = 0;
+        let mut slice = hdr0;
+        let mut slice_no: usize = 1;
+        let is_intra = hdr0.ftype == FrameType::I;
+        let mut skip_run: usize = 0;
+        let mut imode = IntraModeState::new(mb_w);
+        let mut q = hdr0.quant;
+
+        let mut sstate = SState::new();
+        let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
+
+        self.is_b = hdr0.ftype == FrameType::B;
+        if hdr0.ftype != FrameType::B {
+            self.last_ts = self.next_ts;
+            self.next_ts = hdr0.pts;
+            if self.last_ts > self.next_ts {
+                self.base_ts += 1 << 13;
+            }
+        }
+        let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
+        let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
+        sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
+        sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
+        if sstate.trb != 0 {
+            self.ratio1 = ((sstate.trb as u32)                         << 14) / (sstate.trd as u32);
+            self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
+        } else {
+            self.ratio1 = 1 << 14 >> 1;
+            self.ratio2 = 1 << 14 >> 1;
+        }
+        //todo validate against ref frame
+
+//println!(" frame {:?} pts {} {}x{} trd = {} trb = {}", hdr0.ftype, hdr0.pts, hdr0.width, hdr0.height, sstate.trd, sstate.trb);
+
+        let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
+        let bufret = alloc_video_buffer(vinfo, 4);
+        if let Err(_) = bufret { return Err(DecoderError::InvalidData); }
+        let mut bufinfo = bufret.unwrap();
+        let mut buf = bufinfo.get_vbuf().unwrap();
+
+        sstate.q = q;
+        sstate.has_top = false;
+        sstate.mb_w = mb_w;
+        sstate.mb_h = mb_h;
+        sstate.set_idx = hdr0.set_idx;
+
+        self.mvi.resize(mb_w, mb_h);
+        for mb_y in 0..mb_h {
+            sstate.mb_y = mb_y;
+            sstate.has_left = false;
+            for mb_x in 0..mb_w {
+                sstate.mb_x = mb_x;
+                if mb_pos == slice.end {
+                    slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
+//println!(" new slice! {}-{}", mb_pos, slice.end);
+                    validate!(slice.fits(&hdr0));
+                    q = slice.quant;
+                    slice_no += 1;
+                    imode.reset();
+                    sstate.q        = q;
+                    sstate.has_top  = false;
+                    sstate.has_left = false;
+                    sstate.set_idx  = slice.set_idx;
+                }
+                sstate.has_top = (mb_pos - slice.start) >= mb_w;
+                sstate.has_tl  = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
+                sstate.has_tr  = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
+                imode.set_mb_x(mb_x);
+                let mbh = if is_intra {
+                        let is_i16 = br.read_bool()?;
+                        self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
+                    } else {
+                        if skip_run == 0 {
+                            let mbtype;
+                            if self.is_rv30 {
+                                mbtype = MBType::Invalid;
+                            } else {
+                                let mut hist = MBHist::new(hdr0.ftype);
+                                if sstate.has_top  {
+                                    hist.add(mbinfo[mb_pos - mb_w].mbtype);
+                                    if sstate.has_tr   { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
+                                }
+                                if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
+                                if sstate.has_tl   { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
+                                mbtype = hist.get_mbtype();
+                            }
+                            self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
+                        } else {
+                            skip_run -= 1;
+                            MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
+                        }
+                    };
+                if !mbh.mbtype.is_intra() {
+                    let mut mvs: [MV; 4] = [ZERO_MV; 4];
+                    for i in 0..mbh.mbtype.get_num_mvs() {
+                        mvs[i] = decode_mv(&mut br)?;
+                    }
+                    if !self.is_b {
+                        self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
+                    } else {
+                        let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, &mbinfo);
+                        self.mvi.fill(mb_x, mb_y, true,  mv_f);
+                        self.mvi.fill(mb_x, mb_y, false, mv_b);
+                    }
+                }
+                let cbp;
+// println!("   mb {}.{} type {:?}", mb_x, mb_y, mbh.mbtype);
+                let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
+                if mbh.mbtype == MBType::MBSkip {
+                    cbp = 0;
+                    if mbh.skip_run > 0 {
+                        skip_run = mbh.skip_run;
+                    }
+                } else {
+                    self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
+                    if mbh.mbtype == MBType::MBP16x16Mix {
+                        self.coderead.select_codes(true, q, slice.set_idx, true);
+                    }
+                    cbp = self.coderead.decode_cbp(&mut br)?;
+// println!("    CBP {:X} @ {}", cbp, br.tell());
+                }
+                sstate.cbp = cbp;
+                if is_intra || mbh.mbtype.is_intra() {
+                    sstate.q_dc = bd.quant_dc(true, q);
+                    self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
+                } else {
+                    imode.fill_block(0);
+                    self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
+                }
+
+                let mi = RV34MBInfo { cbp: cbp, q: q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
+                mbinfo.push(mi);
+                if is_intra {
+                    mbinfo[mb_pos].deblock = 0xFFFF;
+                    mbinfo[mb_pos].cbp_c   = 0xFF;
+                } else {
+                    self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
+                }
+                sstate.has_left = true;
+                mb_pos += 1;
+            }
+            if hdr0.deblock && (mb_y >= 1) {
+                self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_y - 1);
+            }
+            imode.update();
+        }
+        if hdr0.deblock {
+            self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h - 1);
+        }
+/*if self.is_b{
+    let stride = buf.get_stride(0);
+    let mut offset = buf.get_offset(0);
+    let mut data = buf.get_data_mut();
+    let framebuf: &mut [u8] = data.as_mut_slice();
+
+    for _ in 0..mb_h {
+        for x in 0..mb_w {
+            for i in 0..16 { framebuf[offset + x * 16 + 15 + i*stride] = 255; }
+        }
+        for x in 0..mb_w*16 { framebuf[offset+stride*15+x] = 255;}
+        offset += 16 * stride;
+    }
+}*/
+        if !self.is_b {
+            self.ipbs.add_frame(buf);
+            mem::swap(&mut self.mvi, &mut self.ref_mvi);
+            mem::swap(&mut self.mbinfo, &mut mbinfo);
+        }
+
+        Ok((bufinfo, hdr0.ftype, ts))
+    }
+}
diff --git a/src/codecs/real/rv30dsp.rs b/src/codecs/real/rv30dsp.rs
new file mode 100644 (file)
index 0000000..049e002
--- /dev/null
@@ -0,0 +1,435 @@
+use frame::{FrameType, NAVideoBuffer};
+use codecs::MV;
+use codecs::blockdsp::edge_emu;
+use super::rv3040::{RV34DSP, RV34MBInfo};
+
+fn clip8(a: i16) -> u8 {
+    if a < 0 { 0 }
+    else if a > 255 { 255 }
+    else { a as u8 }
+}
+
+fn rv3_filter_h(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, bsize: usize, c1: i16, c2: i16) {
+    for _ in 0..bsize {
+        for x in 0..bsize {
+            dst[didx + x] = clip8((-((src[sidx + x - 1] as i16) + (src[sidx + x + 2] as i16)) + (src[sidx + x + 0] as i16) * c1 + (src[sidx + x + 1] as i16) * c2 + 8) >> 4);
+        }
+        sidx += sstride;
+        didx += dstride;
+    }
+}
+
+fn rv3_filter_v(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, bsize: usize, c1: i16, c2: i16) {
+    for _ in 0..bsize {
+        for x in 0..bsize {
+            dst[didx + x] = clip8((-((src[sidx + x - 1 * sstride] as i16) + (src[sidx + x + 2 * sstride] as i16)) + (src[sidx + x + 0 * sstride] as i16) * c1 + (src[sidx + x + 1 * sstride] as i16) * c2 + 8) >> 4);
+        }
+        sidx += sstride;
+        didx += dstride;
+    }
+}
+
+macro_rules! mc_matrix {
+    ($s: ident, $o: expr, $c1: expr) => (
+            ($c1 * 6) * ($s[$o] as i32) + ($c1 * 9) * ($s[$o + 1] as i32) + ($c1) * ($s[$o + 2] as i32)
+        );
+    ($s: ident, $o: expr, $c1: expr, $d1: expr, $d2: expr) => (
+            (-$c1) * ($s[$o - 1] as i32) + ($c1 * $d1) * ($s[$o] as i32) + ($c1 * $d2) * ($s[$o + 1] as i32) + (-$c1) * ($s[$o + 2] as i32)
+        );
+    ($s: ident, $o: expr, $ss: expr, $c1: expr, $c2: expr, $d1: expr, $d2: expr) => (
+        ((mc_matrix!($s, $o -     $ss,  -1, $d1, $d2) +
+          mc_matrix!($s, $o          , $c1, $d1, $d2) +
+          mc_matrix!($s, $o +     $ss, $c2, $d1, $d2) +
+          mc_matrix!($s, $o + 2 * $ss,  -1, $d1, $d2) + 128) >> 8) as i16
+        );
+    (m22; $s: ident, $o: expr, $ss: expr) => (
+        ((mc_matrix!($s, $o + 0 * $ss, 6) +
+          mc_matrix!($s, $o + 1 * $ss, 9) +
+          mc_matrix!($s, $o + 2 * $ss, 1) + 128) >> 8) as i16
+        );
+}
+
+macro_rules! mc_func {
+    (copy; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                let d = &mut dst[didx..][..$size];
+                let s = &src[sidx..][..$size];
+                for x in 0..$size { d[x] = s[x]; }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+    (hor; $name: ident, $c1: expr, $c2: expr, $size: expr) => (
+        fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], sidx: usize, sstride: usize) {
+            rv3_filter_h(dst, didx, dstride, src, sidx, sstride, $size, $c1, $c2);
+        }
+        );
+    (ver; $name: ident, $c1: expr, $c2: expr, $size: expr) => (
+        fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], sidx: usize, sstride: usize) {
+            rv3_filter_v(dst, didx, dstride, src, sidx, sstride, $size, $c1, $c2);
+        }
+        );
+    (m11; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 12, 6, 12, 6));
+                }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+    (m12; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 6, 12, 12, 6));
+                }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+    (m21; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = clip8(mc_matrix!(src, sidx + x, sstride, 12, 6, 6, 12));
+                }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+    (m22; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = clip8(mc_matrix!(m22; src, sidx + x, sstride));
+                }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+}
+mc_func!(copy; copy_16, 16);
+mc_func!(copy; copy_8,   8);
+mc_func!(hor;  luma_mc_10_16, 12, 6, 16);
+mc_func!(hor;  luma_mc_20_16, 6, 12, 16);
+mc_func!(hor;  luma_mc_10_8,  12, 6,  8);
+mc_func!(hor;  luma_mc_20_8,  6, 12,  8);
+mc_func!(ver;  luma_mc_01_16, 12, 6, 16);
+mc_func!(ver;  luma_mc_02_16, 6, 12, 16);
+mc_func!(ver;  luma_mc_01_8,  12, 6,  8);
+mc_func!(ver;  luma_mc_02_8,  6, 12,  8);
+mc_func!(m11;  luma_mc_11_16,        16);
+mc_func!(m11;  luma_mc_11_8,          8);
+mc_func!(m21;  luma_mc_21_16,        16);
+mc_func!(m21;  luma_mc_21_8,          8);
+mc_func!(m12;  luma_mc_12_16,        16);
+mc_func!(m12;  luma_mc_12_8,          8);
+mc_func!(m22;  luma_mc_22_16,        16);
+mc_func!(m22;  luma_mc_22_8,          8);
+
+const RV30_CHROMA_FRAC1: [u16; 3] = [ 8, 5, 3 ];
+const RV30_CHROMA_FRAC2: [u16; 3] = [ 0, 3, 5 ];
+fn rv30_chroma_mc(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, size: usize, x: usize, y: usize) {
+    if (x == 0) && (y == 0) {
+        for _ in 0..size {
+            for x in 0..size { dst[didx + x] = src[sidx + x]; }
+            didx += dstride;
+            sidx += sstride;
+        }
+        return;
+    }
+    let a = RV30_CHROMA_FRAC1[x] * RV30_CHROMA_FRAC1[y];
+    let b = RV30_CHROMA_FRAC2[x] * RV30_CHROMA_FRAC1[y];
+    let c = RV30_CHROMA_FRAC1[x] * RV30_CHROMA_FRAC2[y];
+    let d = RV30_CHROMA_FRAC2[x] * RV30_CHROMA_FRAC2[y];
+    for _ in 0..size {
+        for x in 0..size {
+            dst[didx + x] = ((a * (src[sidx + x] as u16)
+                            + b * (src[sidx + x + 1] as u16)
+                            + c * (src[sidx + x + sstride] as u16)
+                            + d * (src[sidx + x + 1 + sstride] as u16) + 32) >> 6) as u8;
+        }
+        didx += dstride;
+        sidx += sstride;
+    }
+}
+
+pub struct RV30DSP {
+    luma_mc: [[fn (&mut [u8], usize, usize, &[u8], usize, usize); 9]; 2],
+}
+
+impl RV30DSP {
+    pub fn new() -> Self {
+        RV30DSP {
+            luma_mc: [
+                    [ copy_16,       luma_mc_10_16,  luma_mc_20_16,
+                      luma_mc_01_16, luma_mc_11_16,  luma_mc_21_16,
+                      luma_mc_02_16, luma_mc_12_16,  luma_mc_22_16 ],
+                    [ copy_8,        luma_mc_10_8,   luma_mc_20_8,
+                      luma_mc_01_8,  luma_mc_11_8,   luma_mc_21_8,
+                      luma_mc_02_8,  luma_mc_12_8,   luma_mc_22_8  ] ],
+        }
+    }
+}
+
+macro_rules! el {
+    ($src: ident, $o: expr) => ($src[$o] as i16);
+}
+
+fn clip_symm(a: i16, lim: i16) -> i16 {
+    if a < -lim {
+        -lim
+    } else if a > lim {
+        lim
+    } else {
+        a
+    }
+}
+
+const RV30_LOOP_FILTER_STRENGTH: [i16; 32] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+    2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5
+];
+
+macro_rules! test_bit {
+    ($pat: expr, $x: expr) => ( (($pat >> $x) & 1) != 0 )
+}
+
+fn rv30_loop_filter4(pix: &mut [u8], mut off: usize, step: usize, stride: usize, lim: i16) {
+    for _ in 0..4 {
+        let a = el!(pix, off - 2*step);
+        let b = el!(pix, off -   step);
+        let c = el!(pix, off);
+        let d = el!(pix, off +   step);
+        let diff0 = ((a - d) - (b - c) * 4) >> 3;
+        let diff = clip_symm(diff0, lim);
+        pix[off - step] = clip8(b + diff);
+        pix[off       ] = clip8(c - diff);
+        off += stride;
+    }
+}
+
+fn rv30_div_mv(mv: i16) -> (i16, usize) {
+    let i = mv / 3;
+    let f = mv - i * 3;
+    if f < 0 {
+        (i - 1, (f + 3) as usize)
+    } else {
+        (i, f as usize)
+    }
+}
+
+fn check_pos(x: usize, y: usize, size: usize, w: usize, h: usize, dx: i16, dy: i16, e0: isize, e1: isize, e2: isize, e3: isize) -> bool {
+    let xn = (x as isize) + (dx as isize);
+    let yn = (y as isize) + (dy as isize);
+
+    (xn - e0 >= 0) && (xn + (size as isize) + e1 <= (w as isize)) && (yn - e2 >= 0) && (yn + (size as isize) + e3 <= (h as isize))
+}
+
+const RV30_EDGE1: [isize; 3] = [ 0, 1, 1 ];
+const RV30_EDGE2: [isize; 3] = [ 0, 2, 2 ];
+
+impl RV34DSP for RV30DSP {
+    fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, _ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize) {
+        let mut offs:   [usize; 3] = [0; 3];
+        let mut stride: [usize; 3] = [0; 3];
+
+        for comp in 0..3 {
+            stride[comp] = frame.get_stride(comp);
+            let start = if comp == 0 { row * 16 } else { row * 8 };
+            offs[comp] = frame.get_offset(comp) + start * stride[comp];
+        }
+
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        // vertical filter
+        let mut left_cbp = 0;
+        let mut left_lim = 0;
+        let mut left_dbk = 0;
+        let mut mb_pos: usize = row * mb_w;
+        for mb_x in 0..mb_w {
+            let cur_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos].q as usize];
+            let cur_dbk = mbinfo[mb_pos].deblock;
+            let cur_cbp = mbinfo[mb_pos].cbp_c;
+            let xstart = if mb_x == 0 { 1 } else { 0 };
+            for y in 0..4 {
+                let yoff = offs[0] + mb_x * 16 + y * 4 * stride[0];
+                for x in xstart..4 {
+                    let cs = x + y*4;
+                    let loc_lim;
+
+                    if test_bit!(cur_dbk, cs) {
+                        loc_lim = cur_lim;
+                    } else if (x == 0) && test_bit!(left_dbk, cs + 3) {
+                        loc_lim = left_lim;
+                    } else if (x != 0) && test_bit!(cur_dbk,  cs - 1) {
+                        loc_lim = cur_lim;
+                    } else {
+                        loc_lim = 0;
+                    }
+                    if loc_lim != 0 {
+                        rv30_loop_filter4(dst, yoff + x * 4, 1, stride[0], loc_lim);
+                    }
+                }
+            }
+
+            for comp in 1..3 {
+                for y in 0..2 {
+                    let coff = offs[comp] + mb_x * 8 + y * 4 * stride[comp];
+                    for x in xstart..2 {
+                        let cs = x + y * 2 + (comp - 1) * 4;
+                        let loc_lim;
+
+                        if test_bit!(cur_cbp, cs) {
+                            loc_lim = cur_lim;
+                        } else if (x == 0) && test_bit!(left_cbp, cs + 1) {
+                            loc_lim = left_lim;
+                        } else if (x != 0) && test_bit!(cur_cbp,  cs - 1) {
+                            loc_lim = cur_lim;
+                        } else {
+                            loc_lim = 0;
+                        }
+                        if loc_lim != 0 {
+                            rv30_loop_filter4(dst, coff + x * 4, 1, stride[comp], loc_lim);
+                        }
+                    }
+                }
+            }
+
+            left_lim = cur_lim;
+            left_dbk = cur_dbk;
+            left_cbp = cur_cbp;
+            mb_pos += 1;
+        }
+
+        // horizontal filter
+        let mut mb_pos: usize = row * mb_w;
+        for mb_x in 0..mb_w {
+            let cur_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos].q as usize];
+            let cur_dbk = mbinfo[mb_pos].deblock;
+            let cur_cbp = mbinfo[mb_pos].cbp_c;
+            let ystart = if row == 0 { 1 } else { 0 };
+            let top_lim;
+            let top_dbk;
+            let top_cbp;
+            if row > 0 {
+                top_lim = RV30_LOOP_FILTER_STRENGTH[mbinfo[mb_pos - mb_w].q as usize];
+                top_dbk = mbinfo[mb_pos - mb_w].deblock;
+                top_cbp = mbinfo[mb_pos - mb_w].cbp_c;
+            } else {
+                top_lim = 0;
+                top_dbk = 0;
+                top_cbp = 0;
+            }
+            for y in ystart..4 {
+                let yoff = offs[0] + mb_x * 16 + y * 4 * stride[0];
+                for x in 0..4 {
+                    let cs = x + y*4;
+                    let loc_lim;
+
+                    if test_bit!(cur_dbk, cs) {
+                        loc_lim = cur_lim;
+                    } else if (y == 0) && test_bit!(top_dbk, cs + 12) {
+                        loc_lim = top_lim;
+                    } else if (y != 0) && test_bit!(cur_dbk, cs - 4) {
+                        loc_lim = cur_lim;
+                    } else {
+                        loc_lim = 0;
+                    }
+                    if loc_lim != 0 {
+                        rv30_loop_filter4(dst, yoff + x * 4, stride[0], 1, loc_lim);
+                    }
+                }
+            }
+
+            for comp in 1..3 {
+                for y in ystart..2 {
+                    let coff = offs[comp] + mb_x * 8 + y * 4 * stride[comp];
+                    for x in 0..2 {
+                        let cs = x + y * 2 + (comp - 1) * 4;
+                        let loc_lim;
+
+                        if test_bit!(cur_cbp, cs) {
+                            loc_lim = cur_lim;
+                        } else if (y == 0) && test_bit!(top_cbp, cs + 2) {
+                            loc_lim = top_lim;
+                        } else if (y != 0) && test_bit!(cur_cbp, cs - 2) {
+                            loc_lim = cur_lim;
+                        } else {
+                            loc_lim = 0;
+                        }
+                        if loc_lim != 0 {
+                            rv30_loop_filter4(dst, coff + x * 4, stride[comp], 1, loc_lim);
+                        }
+                    }
+                }
+            }
+
+            mb_pos += 1;
+        }
+    }
+    fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool) {
+        let size: usize = if use16 { 16 } else { 8 };
+        let dstride = frame.get_stride(0);
+        let doffset = frame.get_offset(0) + (if !avg { x + y * dstride } else { 0 });
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let (w_, h_) = prev_frame.get_dimensions(0);
+        let w = (w_ + 15) & !15;
+        let h = (h_ + 15) & !15;
+
+        let (dx, cx) = rv30_div_mv(mv.x);
+        let (dy, cy) = rv30_div_mv(mv.y);
+        let mode = cx + cy * 3;
+
+        if check_pos(x, y, size, w, h, dx, dy, RV30_EDGE1[cx], RV30_EDGE2[cx], RV30_EDGE1[cy], RV30_EDGE2[cy]) {
+            let sstride = prev_frame.get_stride(0);
+            let mut soffset = prev_frame.get_offset(0) + x + y * sstride;
+            let data = prev_frame.get_data();
+            let src: &[u8] = data.as_slice();
+            soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize;
+            self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, src, soffset, sstride);
+        } else {
+            let mut ebuf: [u8; 32*20] = [0; 32*20];
+            edge_emu(prev_frame, (x as isize) + (dx as isize) - 1, (y as isize) + (dy as isize) - 1, 16+3, 16+3, &mut ebuf, 32, 0);
+            self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, &ebuf, 32 + 1, 32);
+        }
+    }
+    fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool) {
+        let size: usize = if use8 { 8 } else { 4 };
+        let dstride = frame.get_stride(comp);
+        let doffset = frame.get_offset(comp) + (if !avg { x + y * dstride } else { 0 });
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let (w_, h_) = prev_frame.get_dimensions(comp);
+        let w = (w_ + 7) & !7;
+        let h = (h_ + 7) & !7;
+
+        let (dx, cx) = rv30_div_mv(mv.x / 2);
+        let (dy, cy) = rv30_div_mv(mv.y / 2);
+
+        if check_pos(x, y, size, w, h, dx, dy, 0, 1, 0, 1) {
+            let sstride = prev_frame.get_stride(comp);
+            let mut soffset = prev_frame.get_offset(comp) + x + y * sstride;
+            let data = prev_frame.get_data();
+            let src: &[u8] = data.as_slice();
+            soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize;
+            rv30_chroma_mc(dst, doffset, dstride, src, soffset, sstride, size, cx, cy);
+        } else {
+            let mut ebuf: [u8; 16*10] = [0; 16*10];
+            edge_emu(prev_frame, (x as isize) + (dx as isize), (y as isize) + (dy as isize), 8+1, 8+1, &mut ebuf, 16, comp);
+            rv30_chroma_mc(dst, doffset, dstride, &ebuf, 0, 16, size, cx, cy);
+        }
+    }
+}
diff --git a/src/codecs/real/rv34codes.rs b/src/codecs/real/rv34codes.rs
new file mode 100644 (file)
index 0000000..a617535
--- /dev/null
@@ -0,0 +1,4284 @@
+use codecs::DecoderResult;
+use io::bitreader::BitReader;
+use io::codebook::*;
+
+struct CBPSet {
+    cbp_pattern:    Codebook<u16>,
+    cbp:            [Codebook<u8>; 4],
+}
+
+struct CoefSet {
+    blk_pattern0:   Vec<Codebook<u16>>,
+    blk_pattern1:   Vec<Codebook<u16>>,
+    blk_pattern2:   Vec<Codebook<u16>>,
+}
+
+struct FullSet {
+    cbp:    Vec<CBPSet>,
+    cset:   CoefSet,
+    coeffs: Codebook<u16>,
+}
+
+struct RV34CodeReader {
+    lengths: Vec<u8>,
+    codes:   Vec<u32>,
+    syms:    Vec<u16>,
+}
+
+impl RV34CodeReader {
+    fn new(data: &'static [u8]) -> Self {
+        let len = data.len();
+        let mut lengths: Vec<u8> = Vec::with_capacity(len);
+        let mut codes: Vec<u32> = Vec::with_capacity(len);
+        let mut syms: Vec<u16> = Vec::with_capacity(len);
+        let mut counts: [u32; 17] = [0; 17];
+        let mut prefix: [u32; 17] = [0; 17];
+        for i in 0..len {
+            if data[i] > 0 {
+                counts[data[i] as usize] += 1;
+            }
+        }
+        for i in 0..16 {
+            prefix[i + 1] = (prefix[i] + counts[i]) << 1;
+        }
+        for i in 0..len {
+            if data[i] == 0 { continue; }
+            lengths.push(data[i]);
+            let bits = data[i] as usize;
+            codes.push(prefix[bits]);
+            prefix[bits] += 1;
+            syms.push(i as u16);
+        }
+
+        RV34CodeReader { codes: codes, lengths: lengths, syms: syms }
+    }
+}
+
+impl CodebookDescReader<u16> for RV34CodeReader {
+    fn bits(&mut self, idx: usize) -> u8    { self.lengths[idx] }
+    fn code(&mut self, idx: usize) -> u32   { self.codes[idx] }
+    fn sym (&mut self, idx: usize) -> u16   { self.syms[idx] }
+    fn len (&mut self)             -> usize { self.lengths.len() }
+}
+
+struct RV34CBPCodeReader {
+    lengths: Vec<u8>,
+    codes:   Vec<u32>,
+    syms:    Vec<u8>,
+}
+
+const RV34_CBP_SYMS: [u8; 16] = [
+    0x00, 0x20, 0x10, 0x30, 0x02, 0x22, 0x12, 0x32,
+    0x01, 0x21, 0x11, 0x31, 0x03, 0x23, 0x13, 0x33
+];
+
+impl RV34CBPCodeReader {
+    fn new(data: &'static [u8]) -> Self {
+        let len = data.len();
+        let mut lengths: Vec<u8> = Vec::with_capacity(len);
+        let mut codes: Vec<u32> = Vec::with_capacity(len);
+        let mut syms: Vec<u8> = Vec::with_capacity(len);
+        let mut counts: [u32; 17] = [0; 17];
+        let mut prefix: [u32; 17] = [0; 17];
+        for i in 0..len {
+            if data[i] > 0 {
+                counts[data[i] as usize] += 1;
+            }
+        }
+        for i in 0..16 {
+            prefix[i + 1] = (prefix[i] + counts[i]) << 1;
+        }
+        for i in 0..len {
+            if data[i] == 0 { continue; }
+            lengths.push(data[i]);
+            let bits = data[i] as usize;
+            codes.push(prefix[bits]);
+            prefix[bits] += 1;
+            syms.push(RV34_CBP_SYMS[i]);
+        }
+
+        RV34CBPCodeReader { codes: codes, lengths: lengths, syms: syms }
+    }
+}
+
+impl CodebookDescReader<u8> for RV34CBPCodeReader {
+    fn bits(&mut self, idx: usize) -> u8    { self.lengths[idx] }
+    fn code(&mut self, idx: usize) -> u32   { self.codes[idx] }
+    fn sym (&mut self, idx: usize) -> u8    { self.syms[idx] }
+    fn len (&mut self)             -> usize { self.lengths.len() }
+}
+
+impl CBPSet {
+    fn new(intra: bool, set: usize, subset: usize) -> Self {
+        if intra {
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_CBPPAT[set][subset]);
+            let cbp_pat = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 0*2]);
+            let cbp0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 1*2]);
+            let cbp1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 2*2]);
+            let cbp2 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTRA_CBP[set][subset + 3*2]);
+            let cbp3 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            CBPSet { cbp_pattern: cbp_pat, cbp: [cbp0, cbp1, cbp2, cbp3] }
+        } else {
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_CBPPAT[set]);
+            let cbp_pat = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][0]);
+            let cbp0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][1]);
+            let cbp1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][2]);
+            let cbp2 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CBPCodeReader::new(&RV34_INTER_CBP[set][3]);
+            let cbp3 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            CBPSet { cbp_pattern: cbp_pat, cbp: [cbp0, cbp1, cbp2, cbp3] }
+        }
+    }
+}
+
+impl CoefSet {
+    fn new(intra: bool, set: usize) -> Self {
+        if intra {
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][0]);
+            let first0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][1]);
+            let first1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][2]);
+            let first2 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_FIRSTPAT[set][3]);
+            let first3 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let firsts: Vec<Codebook<u16>> = vec![first0, first1, first2, first3];
+
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_SECONDPAT[set][0]);
+            let second0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_SECONDPAT[set][1]);
+            let second1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let seconds: Vec<Codebook<u16>> = vec![second0, second1];
+
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_THIRDPAT[set][0]);
+            let third0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_THIRDPAT[set][1]);
+            let third1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let thirds: Vec<Codebook<u16>> = vec![third0, third1];
+
+            CoefSet { blk_pattern0: firsts, blk_pattern1: seconds, blk_pattern2: thirds }
+        } else {
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_FIRSTPAT[set][0]);
+            let first0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_FIRSTPAT[set][1]);
+            let first1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let firsts: Vec<Codebook<u16>> = vec![first0, first1];
+
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_SECONDPAT[set][0]);
+            let second0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_SECONDPAT[set][1]);
+            let second1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let seconds: Vec<Codebook<u16>> = vec![second0, second1];
+
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_THIRDPAT[set][0]);
+            let third0 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_THIRDPAT[set][1]);
+            let third1 = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            let thirds: Vec<Codebook<u16>> = vec![third0, third1];
+
+            CoefSet { blk_pattern0: firsts, blk_pattern1: seconds, blk_pattern2: thirds }
+        }
+    }
+}
+
+impl FullSet {
+    fn new(intra: bool, set: usize) -> Self {
+        if intra {
+            let cbp0 = CBPSet::new(intra, set, 0);
+            let cbp1 = CBPSet::new(intra, set, 1);
+            let cbp: Vec<CBPSet> = vec![cbp0, cbp1];
+            let cset = CoefSet::new(intra, set);
+            let mut coderead = RV34CodeReader::new(&RV34_INTRA_COEFFS[set]);
+            let coeffs = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            FullSet { cbp: cbp, cset: cset, coeffs: coeffs }
+        } else {
+            let cbp0 = CBPSet::new(intra, set, 0);
+            let cbp: Vec<CBPSet> = vec![cbp0];
+            let cset = CoefSet::new(intra, set);
+            let mut coderead = RV34CodeReader::new(&RV34_INTER_COEFFS[set]);
+            let coeffs = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            FullSet { cbp: cbp, cset: cset, coeffs: coeffs }
+        }
+    }
+}
+
+fn decode_coeff(br: &mut BitReader, ccodes: &Codebook<u16>, val: u8, esc: u8, quant: u16) -> DecoderResult<i16> {
+    if val == 0 { return Ok(0); }
+    let mut nval = if val == esc {
+            let mut c = br.read_cb(ccodes)? as i16;
+            if c > 23 {
+                c -= 23;
+                c = (1 << c) + (br.read(c as u8)? as i16) + 22;
+            }
+            c += esc as i16;
+            c
+        } else {
+            val as i16
+        };
+    if br.read_bool()? { nval = -nval; }
+    nval = (((nval as i32) * (quant as i32) + 8) >> 4) as i16;
+    Ok(nval)
+}
+
+fn decode_subblock3(br: &mut BitReader, ccodes: &Codebook<u16>, idx: usize, q2: u16, q3: u16, q4: u16, coeffs: &mut [i16]) -> DecoderResult<()> {
+    let flags = RV34_MODULO_THREE_TABLE[idx];
+    coeffs[0*4 + 0] = decode_coeff(br, ccodes, (flags >> 6) & 3, 3, q2)?;
+    coeffs[0*4 + 1] = decode_coeff(br, ccodes, (flags >> 4) & 3, 2, q3)?;
+    coeffs[1*4 + 0] = decode_coeff(br, ccodes, (flags >> 2) & 3, 2, q3)?;
+    coeffs[1*4 + 1] = decode_coeff(br, ccodes, (flags >> 0) & 3, 2, q4)?;
+    Ok(())
+}
+fn decode_subblock1(br: &mut BitReader, ccodes: &Codebook<u16>, idx: usize, q2: u16, coeffs: &mut [i16]) -> DecoderResult<()> {
+    let val = RV34_MODULO_THREE_TABLE[idx] >> 6;
+    coeffs[0] = decode_coeff(br, ccodes, val, 3, q2)?;
+    Ok(())
+}
+fn decode_subblock(br: &mut BitReader, ccodes: &Codebook<u16>, idx: usize, invert: bool, q4: u16, coeffs: &mut [i16]) -> DecoderResult<()> {
+    let flags = RV34_MODULO_THREE_TABLE[idx];
+    coeffs[0*4 + 0] = decode_coeff(br, ccodes, (flags >> 6) & 3, 3, q4)?;
+    if !invert {
+        coeffs[0*4 + 1] = decode_coeff(br, ccodes, (flags >> 4) & 3, 2, q4)?;
+        coeffs[1*4 + 0] = decode_coeff(br, ccodes, (flags >> 2) & 3, 2, q4)?;
+    } else {
+        coeffs[1*4 + 0] = decode_coeff(br, ccodes, (flags >> 4) & 3, 2, q4)?;
+        coeffs[0*4 + 1] = decode_coeff(br, ccodes, (flags >> 2) & 3, 2, q4)?;
+    }
+    coeffs[1*4 + 1] = decode_coeff(br, ccodes, (flags >> 0) & 3, 2, q4)?;
+    Ok(())
+}
+
+#[allow(dead_code)]
+pub struct RV34Codes {
+    intra_set:  Vec<FullSet>,
+    inter_set:  Vec<FullSet>,
+    is_intra:   bool,
+    is_16:      bool,
+    set_idx:    usize,
+    subset_idx: usize,
+}
+
+impl RV34Codes {
+    pub fn new() -> Self {
+        let mut iset: Vec<FullSet> = Vec::with_capacity(5);
+        for set in 0..5 { iset.push(FullSet::new(true, set)); }
+        let mut pset: Vec<FullSet> = Vec::with_capacity(7);
+        for set in 0..7 { pset.push(FullSet::new(false, set)); }
+        RV34Codes {
+            is_intra: false, is_16: false, set_idx: 0, subset_idx: 0,
+            intra_set: iset, inter_set: pset,
+        }
+    }
+    pub fn select_codes(&mut self, is_intra: bool, quant: u8, subset: usize, is_16: bool) {
+        let mut idx = quant as usize;
+        if (subset == 2) && (idx < 19) { idx += 10; }
+        else if (subset != 0) && (idx < 26) { idx += 5; }
+        if idx > 30 { idx = 30; }
+
+        if is_intra {
+            self.set_idx = RV34_SET_IDX_INTRA[idx];
+        } else {
+            self.set_idx = RV34_SET_IDX_INTER[idx];
+        }
+        self.is_intra   = is_intra || is_16;
+        self.is_16      = is_16;
+        self.subset_idx = subset;
+    }
+    pub fn decode_cbp(&mut self, br: &mut BitReader) -> DecoderResult<u32> {
+        let codeset = if self.is_intra {
+                &self.intra_set[self.set_idx].cbp[self.is_16 as usize]
+            } else {
+                &self.inter_set[self.set_idx].cbp[0]
+            };
+        let code = br.read_cb(&codeset.cbp_pattern)?;
+        let pattern = code & 0xF;
+        let mmode   = (code >> 4) as usize;
+        let mut cbp: u32 = 0;
+
+        let ones = RV34_ONES_COUNT[pattern as usize];
+
+        for i in 0..4 {
+            if ((pattern >> (3 - i)) & 1) != 0 {
+                let code = br.read_cb(&codeset.cbp[ones])? as u32;
+                cbp |= code << RV34_CBP_SHIFTS[i];
+            }
+        }
+
+        for i in 0..4 {
+            let t = (RV34_MODULO_THREE_TABLE[mmode] >> (6 - 2*i)) & 3;
+            if t == 1 { cbp |= RV34_CBP_MASKS[br.read(1)? as usize] << i; }
+            if t == 2 { cbp |= RV34_CBP_MASKS[2]                    << i; }
+        }
+
+        Ok(cbp)
+    }
+    pub fn decode_block(&mut self, br: &mut BitReader, coeffs: &mut [i16], idx0: usize, idx1: usize, q2: u16, q3: u16, q4: u16) -> DecoderResult<bool> {
+        let codeset = if self.is_intra {
+                &self.intra_set[self.set_idx].cset
+            } else {
+                &self.inter_set[self.set_idx].cset
+            };
+        let ccodes = if self.is_intra {
+                &self.intra_set[self.set_idx].coeffs
+            } else {
+                &self.inter_set[self.set_idx].coeffs
+            };
+        let blkcp = br.read_cb(&codeset.blk_pattern0[idx0])?;
+        let coded = blkcp & 0x7;
+        let idx   = (blkcp >> 3) as usize;
+        let mut has_ac = true;
+
+        if (RV34_MODULO_THREE_TABLE[idx] & 0x3F) != 0 {
+            decode_subblock3(br, ccodes, idx, q2, q3, q4, coeffs)?;
+        } else {
+            decode_subblock1(br, ccodes, idx, q2, coeffs)?;
+            if coded == 0 {
+                return Ok(false);
+            }
+            has_ac = false;
+        }
+
+        if (coded & 4) != 0 {
+            let idx = br.read_cb(&codeset.blk_pattern1[idx1])? as usize;
+            decode_subblock(br, ccodes, idx, false, q4, &mut coeffs[2..])?;
+        }
+        if (coded & 2) != 0 {
+            let idx = br.read_cb(&codeset.blk_pattern1[idx1])? as usize;
+            decode_subblock(br, ccodes, idx, true, q4, &mut coeffs[8..])?;
+        }
+        if (coded & 1) != 0 {
+            let idx = br.read_cb(&codeset.blk_pattern2[idx1])? as usize;
+            decode_subblock(br, ccodes, idx, false, q4, &mut coeffs[10..])?;
+        }
+
+        Ok(has_ac || (coded != 0))
+    }
+}
+
+const RV34_SET_IDX_INTRA: [usize; 31] = [
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+    2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0
+];
+const RV34_SET_IDX_INTER: [usize; 31] = [
+    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3,
+    3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6
+];
+
+const RV34_ONES_COUNT: [usize; 16] = [ 0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 2, 1, 2, 2, 3 ];
+const RV34_CBP_SHIFTS: [u32; 4] = [ 0, 2, 8, 10 ];
+const RV34_CBP_MASKS: [u32; 3] = [ 0x100000, 0x010000, 0x110000 ];
+
+const RV34_MODULO_THREE_TABLE: [u8; 108] = [
+    0x00, 0x01, 0x02, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A,
+    0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1A,
+    0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2A,
+
+    0x40, 0x41, 0x42, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A,
+    0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5A,
+    0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, 0x6A,
+
+    0x80, 0x81, 0x82, 0x84, 0x85, 0x86, 0x88, 0x89, 0x8A,
+    0x90, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, 0x99, 0x9A,
+    0xA0, 0xA1, 0xA2, 0xA4, 0xA5, 0xA6, 0xA8, 0xA9, 0xAA,
+
+    0xC0, 0xC1, 0xC2, 0xC4, 0xC5, 0xC6, 0xC8, 0xC9, 0xCA,
+    0xD0, 0xD1, 0xD2, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA,
+    0xE0, 0xE1, 0xE2, 0xE4, 0xE5, 0xE6, 0xE8, 0xE9, 0xEA,
+];
+
+const RV34_INTRA_CBPPAT: &'static [[[u8; 1296]; 2]; 5] = &[
+  [
+    [
+       8, 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10,  6,
+      12, 12, 13, 12, 13, 12, 13, 11, 13, 13, 13, 12, 13, 12, 12,  8,
+      14, 13, 16, 13, 15, 13, 16, 12, 16, 16, 16, 14, 16, 13, 14, 10,
+      12, 13, 12, 12, 13, 13, 13, 12, 13, 13, 12, 12, 13, 12, 12,  8,
+      13, 14, 14, 12, 14, 14, 14, 12, 14, 15, 14, 12, 14, 13, 13,  8,
+      16, 16, 16, 12, 16, 16, 16, 13, 16, 16, 16, 13, 16, 14, 14,  9,
+      14, 16, 13, 13, 16, 16, 16, 14, 15, 16, 14, 13, 15, 15, 14, 10,
+      16, 16, 14, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 15, 14, 10,
+      16, 16, 16, 11, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 15,  9,
+      12, 13, 13, 13, 12, 12, 14, 12, 12, 14, 13, 12, 12, 12, 12,  8,
+      14, 14, 16, 14, 13, 12, 14, 12, 14, 15, 14, 13, 13, 12, 13,  8,
+      16, 16, 16, 15, 16, 13, 16, 13, 16, 16, 16, 15, 16, 13, 15, 10,
+      14, 16, 14, 14, 14, 14, 15, 13, 14, 16, 14, 13, 13, 13, 13,  9,
+      16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 14, 13, 14, 13, 13,  8,
+      16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 14, 16, 14, 14,  9,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 14, 10,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 14, 16, 15, 14,  9,
+      16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 16, 13, 16, 15, 15,  8,
+      14, 16, 16, 16, 14, 14, 16, 14, 16, 16, 16, 15, 13, 13, 14, 10,
+      16, 16, 16, 16, 15, 13, 16, 13, 16, 16, 16, 16, 16, 13, 14, 10,
+      16, 16, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16, 12, 16,  9,
+      16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 14, 14, 10,
+      16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 15, 16, 13, 14,  9,
+      16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16, 13, 14,  8,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 11,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14,  9,
+      16, 16, 16, 14, 16, 15, 16, 11, 16, 16, 16, 14, 16, 14, 14,  8,
+      12, 13, 13, 13, 13, 13, 14, 12, 12, 13, 12, 12, 12, 12, 12,  8,
+      14, 14, 16, 14, 15, 14, 16, 13, 14, 15, 14, 13, 14, 13, 13,  9,
+      16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 14, 16, 14, 16, 10,
+      14, 15, 14, 14, 15, 14, 15, 13, 14, 14, 13, 12, 13, 13, 13,  9,
+      15, 16, 15, 14, 16, 16, 16, 13, 15, 16, 14, 12, 14, 13, 13,  8,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 13, 16, 14, 14,  9,
+      16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 13, 13, 16, 16, 14, 10,
+      16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 13, 16, 14, 14,  9,
+      16, 16, 16, 12, 16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 15,  8,
+      13, 14, 14, 14, 14, 14, 16, 13, 13, 14, 14, 13, 12, 12, 12,  8,
+      16, 16, 16, 14, 15, 14, 16, 13, 15, 16, 14, 13, 13, 12, 13,  8,
+      16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 14, 16, 13, 14,  9,
+      15, 16, 16, 15, 16, 15, 16, 13, 14, 16, 14, 13, 13, 13, 12,  8,
+      16, 16, 16, 14, 16, 14, 15, 12, 15, 15, 14, 12, 13, 12, 12,  7,
+      16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 13, 16, 13, 13,  7,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 14, 14, 16, 14, 13,  9,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 14, 12, 16, 13, 12,  7,
+      16, 16, 16, 12, 16, 16, 16, 11, 16, 16, 15, 12, 16, 13, 13,  6,
+      16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 13, 13, 14, 10,
+      16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 14, 13, 14,  9,
+      16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 16, 16, 12, 14,  8,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14, 13, 13,  9,
+      16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 13, 14, 12, 12,  7,
+      16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13,  6,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 14,  9,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 15, 13, 12,  7,
+      16, 16, 16, 13, 16, 14, 16, 11, 16, 16, 16, 12, 16, 12, 12,  5,
+      14, 16, 15, 16, 16, 16, 16, 15, 14, 15, 14, 14, 13, 14, 13, 10,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 16, 10,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 14, 15, 14, 13, 10,
+      16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, 13, 16, 14, 14,  9,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15,  9,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 13, 16, 16, 13, 10,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 16, 13,  9,
+      16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 12, 16, 16, 14,  8,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 15, 14, 13, 13, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14, 13, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15,  9,
+      16, 16, 16, 16, 16, 16, 16, 15, 15, 16, 14, 14, 14, 13, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 12, 13, 12, 12,  7,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 16, 13, 13,  7,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 14, 13,  9,
+      16, 16, 16, 15, 16, 16, 16, 13, 16, 16, 13, 12, 14, 13, 12,  6,
+      16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 14, 10, 15, 12, 12,  5,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12, 13, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 13, 12, 13,  8,
+      16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 15, 12, 14,  8,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 13, 13, 13,  8,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 15, 13, 12, 11, 12,  6,
+      16, 16, 16, 15, 16, 14, 16, 12, 16, 16, 16, 12, 13, 10, 12,  5,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 13, 14, 12,  8,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 13, 12, 13, 12, 10,  5,
+      16, 16, 16, 13, 16, 13, 16, 10, 16, 16, 13, 10, 13, 10, 10,  1,
+    ], [
+       2,  7,  7,  8,  7,  8,  9,  8,  7,  9,  8,  8,  8,  8,  9,  7,
+       6,  9, 10, 10, 10, 10, 11, 10, 10, 11, 11, 11, 10, 11, 11,  9,
+       9, 11, 12, 12, 12, 13, 14, 13, 13, 14, 14, 13, 13, 13, 14, 11,
+       6, 10,  9, 10, 10, 11, 11, 11, 10, 11, 10, 11, 11, 11, 11,  9,
+       6,  9, 10, 10, 10, 11, 12, 11, 10, 12, 11, 11, 11, 11, 11,  8,
+       9, 11, 12, 12, 12, 13, 13, 13, 12, 14, 14, 13, 13, 13, 13, 10,
+       9, 13, 11, 13, 13, 14, 14, 13, 13, 14, 13, 13, 14, 14, 14, 12,
+       9, 12, 12, 12, 12, 14, 14, 13, 13, 14, 13, 13, 13, 14, 13, 11,
+       8, 12, 12, 11, 12, 14, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11,
+       6, 10, 10, 11,  9, 10, 12, 11, 10, 12, 11, 11, 10, 11, 11,  9,
+       7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 11,  9,
+       9, 12, 13, 13, 12, 12, 14, 13, 13, 14, 14, 13, 14, 13, 14, 11,
+       8, 11, 11, 12, 11, 12, 12, 12, 11, 13, 12, 12, 12, 12, 12, 10,
+       7, 10, 10, 11, 10, 11, 12, 11, 10, 12, 11, 11, 11, 11, 11,  8,
+       9, 11, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 13, 12, 13, 10,
+      10, 13, 13, 14, 14, 14, 15, 14, 14, 15, 14, 15, 14, 14, 14, 12,
+       9, 12, 12, 13, 12, 13, 14, 13, 12, 13, 13, 12, 13, 13, 13, 10,
+       9, 12, 12, 12, 12, 13, 14, 12, 12, 14, 13, 12, 13, 13, 13, 10,
+       9, 12, 13, 13, 11, 13, 14, 13, 13, 14, 14, 14, 12, 13, 13, 11,
+      10, 12, 13, 13, 12, 12, 14, 13, 13, 14, 14, 14, 13, 13, 14, 11,
+      10, 13, 14, 14, 13, 12, 15, 13, 14, 14, 14, 14, 15, 13, 14, 11,
+      11, 14, 14, 14, 13, 14, 15, 14, 14, 15, 15, 14, 13, 14, 14, 12,
+      10, 13, 12, 13, 12, 12, 14, 13, 13, 14, 13, 13, 13, 13, 13, 10,
+      10, 12, 13, 13, 13, 12, 14, 12, 13, 14, 14, 13, 13, 13, 13, 10,
+      13, 15, 16, 16, 15, 15, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14,
+      11, 14, 14, 14, 14, 14, 15, 14, 14, 15, 15, 14, 14, 14, 15, 11,
+      10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 14, 13, 13, 13, 13, 10,
+       6, 10, 10, 11, 10, 11, 12, 11, 10, 12, 10, 11, 10, 11, 11,  9,
+       8, 11, 11, 12, 11, 12, 13, 12, 11, 12, 12, 12, 12, 12, 12, 10,
+      11, 13, 14, 14, 13, 14, 15, 14, 13, 15, 15, 14, 14, 14, 15, 12,
+       7, 11, 10, 12, 11, 12, 12, 12, 11, 12, 11, 12, 11, 12, 12, 10,
+       7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 11,  9,
+      10, 12, 13, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13, 13, 13, 10,
+      10, 13, 12, 14, 13, 14, 14, 14, 13, 14, 12, 14, 15, 14, 14, 11,
+      10, 12, 12, 12, 12, 13, 14, 13, 13, 14, 13, 12, 13, 13, 13, 10,
+       9, 12, 13, 13, 13, 14, 14, 13, 13, 14, 14, 13, 13, 13, 13, 10,
+       7, 10, 10, 11, 10, 11, 12, 11, 10, 12, 12, 11,  9, 11, 11,  9,
+       7, 10, 11, 11, 10, 11, 12, 11, 10, 12, 12, 11, 11, 11, 11,  9,
+      10, 12, 13, 13, 13, 13, 15, 13, 13, 14, 13, 13, 13, 13, 13, 10,
+       8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 12, 11,  9,
+       6,  9,  9, 10,  9, 10, 10, 10,  9, 11, 10, 10,  9, 10, 10,  7,
+       8, 10, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 11, 11,  8,
+      10, 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 13, 13, 13, 13, 11,
+       8, 11, 11, 11, 11, 12, 12, 11, 11, 12, 11, 11, 11, 11, 11,  8,
+       8, 11, 11, 11, 11, 12, 12, 10, 11, 12, 12, 11, 11, 11, 11,  8,
+      10, 13, 13, 13, 12, 13, 14, 13, 12, 14, 14, 14, 10, 13, 13, 11,
+      10, 12, 12, 13, 12, 13, 14, 12, 12, 13, 13, 13, 12, 12, 13, 10,
+      11, 13, 14, 14, 13, 13, 14, 13, 13, 15, 14, 13, 13, 13, 13, 10,
+      10, 12, 13, 13, 12, 13, 14, 13, 13, 14, 14, 13, 12, 13, 13, 11,
+       8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 11, 11, 11,  8,
+       9, 11, 12, 12, 11, 11, 12, 11, 12, 12, 12, 11, 12, 11, 11,  8,
+      12, 15, 14, 14, 14, 15, 15, 14, 14, 15, 15, 14, 14, 14, 15, 12,
+      10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 12, 12, 12,  9,
+       9, 11, 11, 11, 11, 11, 12, 10, 11, 12, 12, 11, 11, 11, 11,  7,
+      10, 13, 13, 13, 13, 14, 15, 14, 13, 14, 14, 14, 12, 14, 15, 12,
+      11, 14, 14, 14, 14, 15, 15, 14, 14, 15, 15, 15, 14, 15, 15, 12,
+      13, 16, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 14,
+      10, 13, 13, 14, 13, 15, 14, 14, 13, 15, 13, 14, 14, 14, 14, 12,
+      10, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 13, 13, 13, 14, 11,
+      12, 14, 14, 14, 14, 15, 15, 14, 14, 15, 15, 14, 15, 14, 14, 12,
+      11, 14, 14, 15, 14, 15, 15, 14, 14, 15, 12, 14, 15, 16, 15, 12,
+      11, 13, 13, 14, 13, 14, 14, 14, 14, 14, 13, 13, 14, 14, 14, 11,
+      11, 14, 14, 14, 14, 15, 15, 14, 14, 16, 14, 13, 14, 14, 14, 11,
+      10, 13, 13, 13, 12, 14, 14, 14, 12, 15, 14, 14, 11, 13, 13, 12,
+      10, 12, 13, 14, 12, 13, 14, 13, 13, 14, 14, 13, 12, 13, 13, 11,
+      12, 14, 14, 15, 14, 15, 16, 15, 15, 15, 15, 15, 14, 14, 15, 12,
+      10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 13, 13, 12, 13, 13, 11,
+       9, 11, 11, 12, 11, 12, 12, 11, 11, 12, 12, 11, 11, 11, 11,  9,
+      10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 13, 12, 13, 12, 12,  9,
+      11, 13, 13, 15, 14, 14, 15, 14, 14, 15, 14, 14, 14, 14, 14, 11,
+      10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 11, 11, 12, 12, 12,  8,
+       9, 12, 12, 11, 12, 12, 13, 11, 12, 12, 12, 11, 12, 11, 11,  8,
+      10, 13, 13, 14, 12, 14, 15, 14, 13, 15, 15, 14, 10, 13, 13, 11,
+      11, 13, 14, 13, 13, 14, 14, 13, 13, 14, 14, 14, 11, 13, 13, 11,
+      12, 14, 14, 14, 14, 14, 15, 14, 15, 16, 15, 14, 13, 13, 14, 11,
+      11, 14, 13, 14, 13, 14, 15, 14, 13, 15, 14, 14, 11, 13, 13, 11,
+       9, 12, 12, 12, 11, 12, 13, 11, 12, 13, 12, 11, 10, 11, 11,  8,
+      10, 12, 12, 12, 12, 12, 13, 11, 12, 12, 12, 11, 11, 11, 11,  8,
+      12, 15, 14, 15, 14, 15, 16, 15, 15, 15, 15, 14, 14, 14, 14, 12,
+      10, 12, 12, 12, 12, 12, 13, 11, 12, 13, 12, 11, 11, 11, 11,  8,
+       8, 10, 10, 10, 10, 10, 11,  9, 10, 11, 10,  9, 10,  9,  9,  5,
+    ],
+  ], [
+    [
+      12, 12, 11,  9, 11, 10, 11,  9, 11, 11, 10,  9,  9,  8,  9,  5,
+      14, 13, 14, 11, 14, 11, 13, 10, 14, 13, 12, 10, 12, 10, 11,  6,
+      16, 13, 16, 12, 16, 12, 16, 11, 16, 14, 16, 12, 15, 12, 13,  8,
+      14, 14, 12, 11, 14, 12, 13, 10, 13, 13, 11, 10, 12, 11, 10,  6,
+      16, 15, 14, 11, 16, 13, 14, 10, 15, 14, 13, 10, 13, 11, 11,  7,
+      16, 16, 16, 11, 16, 14, 16, 11, 16, 16, 15, 12, 15, 13, 13,  8,
+      16, 16, 13, 12, 16, 16, 15, 12, 16, 16, 12, 11, 15, 13, 12,  8,
+      16, 16, 14, 11, 16, 16, 16, 11, 16, 16, 14, 11, 15, 14, 13,  8,
+      16, 16, 15, 10, 16, 16, 16, 10, 16, 16, 15, 11, 16, 14, 14,  8,
+      14, 14, 14, 12, 13, 11, 13, 10, 13, 13, 12, 11, 11, 10, 10,  6,
+      16, 15, 16, 13, 13, 11, 14, 11, 15, 14, 13, 11, 12, 10, 11,  7,
+      16, 15, 16, 14, 16, 11, 16, 11, 16, 16, 16, 13, 16, 12, 13,  8,
+      16, 16, 14, 13, 15, 13, 14, 11, 14, 15, 13, 11, 13, 11, 11,  7,
+      16, 16, 15, 13, 15, 13, 14, 11, 16, 15, 14, 11, 13, 11, 11,  7,
+      16, 16, 16, 13, 16, 13, 16, 11, 16, 16, 16, 12, 16, 12, 13,  8,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 14, 13, 15, 14, 13,  9,
+      16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 14, 12, 15, 13, 13,  8,
+      16, 16, 16, 12, 16, 16, 16, 11, 16, 16, 15, 12, 16, 13, 13,  7,
+      16, 16, 16, 16, 13, 12, 16, 12, 16, 16, 14, 13, 12, 11, 12,  8,
+      16, 16, 16, 15, 14, 11, 16, 11, 16, 16, 16, 13, 14, 11, 13,  8,
+      16, 16, 16, 16, 15, 10, 16, 11, 16, 16, 16, 14, 15, 11, 13,  8,
+      16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 14, 14, 14, 12, 13,  9,
+      16, 16, 16, 15, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13,  8,
+      16, 16, 16, 14, 16, 12, 16, 11, 16, 16, 16, 13, 15, 12, 13,  7,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 14, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 14, 16, 13, 13,  8,
+      16, 16, 16, 14, 16, 14, 16, 10, 16, 16, 16, 13, 16, 13, 13,  7,
+      14, 14, 13, 12, 13, 12, 13, 11, 12, 13, 11, 10, 11, 10, 10,  6,
+      16, 16, 15, 13, 16, 13, 15, 11, 14, 14, 13, 11, 13, 11, 11,  7,
+      16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 13, 16, 13, 14,  9,
+      16, 16, 13, 13, 15, 14, 14, 11, 13, 14, 11, 11, 12, 11, 11,  7,
+      16, 16, 15, 12, 16, 14, 15, 11, 14, 14, 12, 11, 13, 11, 11,  7,
+      16, 16, 16, 13, 16, 14, 16, 12, 16, 16, 14, 12, 16, 13, 13,  8,
+      16, 16, 14, 14, 16, 16, 16, 13, 16, 16, 12, 11, 15, 13, 12,  8,
+      16, 16, 15, 13, 16, 16, 16, 12, 16, 16, 13, 11, 16, 13, 12,  8,
+      16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 14, 11, 16, 14, 13,  7,
+      16, 16, 15, 13, 14, 13, 14, 11, 14, 14, 12, 11, 11, 10, 11,  7,
+      16, 16, 16, 13, 14, 12, 15, 11, 15, 14, 13, 11, 12, 11, 11,  7,
+      16, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 13, 14, 12, 13,  8,
+      16, 16, 15, 13, 15, 14, 14, 12, 14, 14, 12, 11, 12, 11, 11,  7,
+      16, 16, 14, 12, 15, 13, 14, 11, 15, 14, 13, 11, 12, 11, 11,  6,
+      16, 16, 16, 13, 16, 13, 16, 11, 16, 15, 14, 11, 14, 11, 12,  6,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13, 12, 14, 13, 12,  8,
+      16, 16, 15, 13, 16, 14, 15, 11, 16, 16, 13, 11, 14, 12, 11,  6,
+      16, 16, 16, 12, 16, 14, 15, 11, 16, 16, 13, 10, 14, 12, 12,  6,
+      16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 14, 13, 12, 11, 12,  8,
+      16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 15, 13, 13, 11, 12,  8,
+      16, 16, 16, 15, 16, 12, 16, 12, 16, 16, 16, 14, 14, 11, 13,  7,
+      16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 14, 13, 13, 12, 12,  8,
+      16, 16, 16, 14, 15, 13, 15, 11, 16, 15, 14, 12, 13, 11, 11,  6,
+      16, 16, 16, 14, 16, 12, 15, 11, 16, 16, 15, 12, 14, 11, 12,  6,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 15, 13, 14, 13, 12,  8,
+      16, 16, 16, 14, 16, 14, 16, 12, 16, 16, 14, 12, 13, 12, 11,  6,
+      16, 16, 16, 13, 16, 13, 15, 10, 16, 16, 14, 11, 14, 11, 11,  5,
+      16, 16, 15, 14, 16, 16, 16, 13, 14, 14, 12, 12, 12, 12, 12,  8,
+      16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 13, 14, 13, 13,  9,
+      16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 16, 13, 15,  9,
+      16, 16, 14, 15, 16, 16, 16, 14, 14, 16, 12, 12, 13, 13, 12,  8,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 15, 13, 12, 14, 12, 12,  8,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 12, 16, 13, 13,  8,
+      16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 11, 11, 15, 14, 12,  8,
+      16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 12, 11, 15, 13, 12,  8,
+      16, 16, 16, 13, 16, 16, 16, 12, 16, 16, 13, 10, 16, 13, 12,  7,
+      16, 16, 16, 16, 16, 15, 16, 13, 14, 16, 13, 13, 12, 12, 12,  8,
+      16, 16, 16, 15, 16, 14, 16, 13, 16, 16, 14, 13, 13, 12, 12,  8,
+      16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 13, 15, 12, 14,  8,
+      16, 16, 16, 15, 16, 16, 16, 13, 14, 16, 13, 12, 12, 12, 11,  8,
+      16, 16, 16, 14, 16, 14, 16, 12, 14, 14, 13, 11, 13, 11, 11,  6,
+      16, 16, 16, 14, 16, 14, 16, 12, 16, 15, 14, 11, 14, 11, 12,  6,
+      16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 12, 12, 14, 13, 11,  8,
+      16, 16, 15, 14, 16, 16, 16, 12, 16, 15, 12, 11, 13, 12, 11,  6,
+      16, 16, 16, 13, 16, 14, 16, 11, 16, 14, 13, 10, 14, 11, 11,  5,
+      16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 15, 13, 11, 11, 11,  8,
+      16, 16, 16, 16, 16, 15, 16, 13, 16, 16, 16, 13, 12, 11, 12,  7,
+      16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 13, 13, 11, 13,  7,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 14, 13, 12, 12, 11,  7,
+      16, 16, 16, 15, 16, 14, 15, 12, 16, 14, 13, 12, 12, 11, 11,  6,
+      16, 16, 16, 14, 16, 13, 15, 11, 16, 14, 14, 11, 13, 10, 11,  5,
+      16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 13, 12, 12, 12, 11,  7,
+      16, 16, 16, 14, 16, 14, 15, 12, 16, 15, 12, 11, 12, 11, 10,  5,
+      16, 16, 16, 13, 16, 13, 14, 10, 16, 14, 12,  9, 12, 10,  9,  3,
+    ], [
+       2,  6,  6,  7,  6,  7,  8,  7,  7,  8,  7,  8,  7,  8,  8,  5,
+       5,  8,  9,  9,  9,  9, 12, 10, 10, 11, 10, 10, 10, 11, 11,  8,
+       9, 10, 13, 12, 13, 12, 15, 13, 13, 14, 13, 14, 13, 13, 14, 11,
+       5, 10,  9, 10, 10, 10, 12, 10, 10, 12, 10, 11, 11, 11, 11,  8,
+       6,  9, 10,  9, 10, 11, 12, 10, 10, 12, 11, 11, 10, 11, 11,  8,
+       9, 11, 12, 11, 12, 13, 14, 12, 13, 14, 14, 12, 13, 13, 13, 11,
+      10, 13, 11, 12, 14, 14, 15, 13, 13, 15, 12, 13, 14, 14, 14, 12,
+       9, 12, 12, 12, 13, 13, 15, 13, 13, 14, 13, 13, 14, 13, 15, 11,
+       8, 11, 12, 10, 12, 13, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11,
+       5,  9, 10, 10,  9, 10, 12, 11, 10, 12, 11, 11,  9, 11, 11,  9,
+       6, 10, 10, 11, 10, 10, 12, 11, 11, 12, 11, 11, 11, 11, 11,  9,
+       9, 11, 13, 13, 12, 11, 14, 12, 13, 15, 13, 13, 14, 13, 14, 11,
+       8, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 13, 12, 12, 12, 10,
+       7, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11, 11, 11, 12,  9,
+       9, 12, 12, 12, 12, 12, 14, 12, 13, 14, 13, 13, 13, 13, 13, 11,
+      11, 14, 13, 15, 15, 16, 16, 15, 15, 16, 15, 15, 16, 16, 15, 13,
+      10, 12, 13, 13, 13, 14, 15, 13, 13, 14, 13, 13, 14, 14, 14, 11,
+       9, 12, 12, 12, 13, 13, 14, 12, 13, 14, 14, 13, 13, 13, 14, 11,
+       9, 13, 13, 13, 11, 12, 15, 13, 13, 15, 14, 14, 11, 13, 14, 11,
+      10, 13, 13, 13, 12, 12, 15, 13, 13, 15, 14, 14, 13, 13, 14, 11,
+      10, 12, 13, 13, 12, 11, 14, 12, 13, 15, 13, 13, 13, 13, 14, 11,
+      11, 14, 15, 15, 13, 14, 16, 14, 14, 16, 16, 14, 14, 15, 15, 13,
+      10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 14, 14, 13, 13, 14, 11,
+      10, 12, 13, 13, 13, 12, 14, 13, 13, 14, 14, 13, 13, 13, 13, 11,
+      13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      12, 15, 15, 15, 14, 15, 16, 14, 15, 16, 16, 15, 16, 15, 15, 13,
+      10, 12, 12, 12, 13, 13, 14, 12, 13, 14, 13, 13, 13, 13, 13, 11,
+       6, 10, 10, 11, 10, 11, 12, 11, 10, 12, 11, 11, 10, 11, 11,  9,
+       8, 11, 12, 12, 12, 12, 13, 12, 12, 13, 12, 13, 12, 13, 13, 10,
+      11, 13, 15, 14, 15, 14, 16, 14, 15, 16, 16, 14, 15, 15, 15, 13,
+       7, 11, 10, 12, 11, 11, 13, 11, 11, 13, 10, 11, 12, 12, 12, 10,
+       7, 11, 11, 11, 11, 11, 13, 11, 11, 13, 11, 12, 12, 12, 12,  9,
+      10, 12, 13, 13, 13, 13, 15, 13, 14, 15, 14, 14, 14, 14, 15, 11,
+      10, 13, 12, 14, 14, 14, 15, 13, 13, 15, 12, 13, 15, 15, 14, 12,
+      10, 13, 12, 12, 13, 13, 15, 14, 13, 15, 13, 13, 14, 14, 14, 11,
+      10, 13, 13, 12, 13, 14, 15, 13, 13, 15, 13, 13, 14, 14, 14, 11,
+       7, 10, 11, 11, 10, 11, 12, 11, 10, 12, 12, 12,  9, 11, 12,  9,
+       7, 11, 11, 11, 11, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12,  9,
+      10, 12, 14, 13, 13, 13, 16, 13, 14, 16, 14, 14, 13, 13, 14, 11,
+       8, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10,
+       6,  9,  9, 10,  9, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10,  8,
+       8, 11, 11, 11, 12, 11, 13, 11, 12, 13, 12, 12, 12, 12, 12, 10,
+      11, 14, 13, 14, 14, 14, 16, 14, 14, 16, 14, 14, 15, 15, 14, 12,
+       9, 12, 11, 12, 12, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10,
+       8, 11, 11, 11, 11, 11, 13, 11, 12, 12, 12, 12, 12, 12, 12,  9,
+      10, 13, 14, 13, 11, 13, 14, 14, 13, 15, 15, 14, 10, 13, 14, 11,
+      10, 13, 13, 13, 12, 13, 14, 13, 13, 14, 14, 14, 13, 13, 13, 11,
+      10, 13, 14, 13, 13, 12, 15, 13, 14, 15, 14, 14, 14, 13, 14, 12,
+      11, 14, 14, 14, 13, 13, 15, 14, 14, 15, 14, 15, 13, 14, 14, 12,
+       9, 11, 12, 12, 11, 11, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10,
+       9, 11, 12, 12, 12, 11, 13, 11, 12, 13, 12, 12, 12, 12, 12, 10,
+      13, 15, 15, 16, 15, 16, 16, 15, 16, 16, 16, 15, 15, 15, 16, 14,
+      10, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 13, 13, 13, 13, 11,
+       8, 11, 11, 11, 11, 11, 12, 11, 11, 12, 12, 11, 12, 11, 12,  9,
+      11, 14, 14, 15, 14, 15, 15, 14, 13, 15, 14, 15, 12, 14, 15, 13,
+      12, 15, 15, 15, 15, 15, 16, 15, 15, 16, 16, 16, 15, 16, 15, 13,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      11, 14, 13, 15, 14, 14, 16, 14, 14, 16, 13, 14, 15, 14, 15, 12,
+      11, 14, 13, 14, 14, 14, 16, 15, 14, 16, 14, 14, 15, 15, 15, 12,
+      13, 15, 15, 15, 15, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 13,
+      11, 14, 13, 14, 14, 14, 15, 14, 14, 16, 12, 14, 16, 16, 14, 12,
+      11, 14, 14, 14, 14, 15, 16, 15, 14, 16, 13, 14, 16, 15, 14, 12,
+      12, 14, 14, 14, 14, 14, 16, 14, 15, 16, 14, 14, 14, 15, 15, 12,
+      11, 14, 14, 14, 13, 14, 16, 15, 13, 16, 15, 15, 11, 14, 14, 12,
+      11, 14, 14, 15, 14, 14, 16, 14, 14, 15, 14, 14, 13, 15, 15, 12,
+      13, 15, 16, 15, 15, 15, 16, 15, 16, 16, 16, 16, 15, 15, 16, 13,
+      11, 14, 14, 14, 14, 14, 15, 14, 14, 16, 14, 14, 14, 15, 14, 12,
+       9, 12, 12, 12, 12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 12, 10,
+      11, 13, 13, 13, 13, 13, 14, 13, 13, 14, 13, 14, 13, 13, 14, 11,
+      12, 15, 14, 15, 15, 15, 16, 15, 14, 16, 14, 14, 16, 16, 14, 13,
+      10, 12, 12, 12, 12, 12, 14, 12, 13, 13, 12, 12, 13, 13, 13, 10,
+      10, 12, 12, 12, 12, 12, 14, 12, 12, 13, 12, 12, 12, 12, 12, 10,
+      10, 14, 14, 14, 12, 14, 16, 14, 13, 16, 16, 16, 10, 13, 14, 12,
+      11, 14, 14, 14, 13, 14, 16, 14, 14, 16, 15, 14, 12, 13, 14, 12,
+      12, 14, 14, 14, 14, 14, 16, 14, 14, 16, 15, 15, 14, 14, 15, 12,
+      12, 14, 15, 15, 14, 15, 16, 14, 15, 15, 15, 15, 13, 15, 14, 12,
+       9, 12, 12, 12, 12, 13, 13, 12, 12, 13, 13, 12, 11, 12, 12, 10,
+      10, 12, 12, 12, 12, 12, 13, 12, 12, 13, 12, 12, 12, 12, 12, 10,
+      13, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 15, 13,
+      10, 12, 12, 13, 12, 13, 13, 12, 13, 14, 13, 13, 12, 13, 13, 10,
+       7, 10, 10, 10, 10, 10, 11, 10, 10, 11, 10, 10, 10, 10, 10,  7,
+    ],
+  ], [
+    [
+      10, 10,  9,  8,  9,  8,  9,  7,  9,  9,  8,  7,  8,  7,  7,  4,
+      13, 11, 12,  9, 12,  9, 12,  9, 12, 11, 11,  9, 10,  9,  9,  6,
+      15, 12, 15, 11, 14, 10, 14, 10, 14, 13, 13, 11, 13, 11, 12,  7,
+      13, 12, 11,  9, 12, 11, 12,  9, 12, 12, 10,  9, 10, 10,  9,  6,
+      14, 13, 12, 10, 13, 12, 13,  9, 13, 12, 11, 10, 12, 11, 10,  6,
+      16, 14, 14, 10, 15, 13, 14, 10, 15, 15, 14, 11, 14, 12, 12,  8,
+      15, 14, 12, 11, 15, 14, 13, 11, 14, 14, 11, 10, 13, 12, 11,  8,
+      15, 16, 13, 11, 16, 14, 14, 11, 15, 15, 12, 10, 14, 13, 12,  8,
+      16, 15, 14, 10, 16, 14, 14, 10, 16, 15, 14, 10, 14, 13, 12,  7,
+      13, 12, 12, 11, 11,  9, 12,  9, 12, 12, 11, 10, 10,  9,  9,  6,
+      13, 13, 14, 12, 12, 10, 12, 10, 14, 13, 12, 11, 11, 10, 10,  7,
+      16, 14, 16, 13, 14, 11, 15, 10, 16, 15, 14, 12, 14, 11, 12,  8,
+      14, 14, 13, 12, 13, 12, 13, 10, 13, 13, 12, 11, 11, 10, 10,  7,
+      15, 14, 14, 12, 14, 12, 13, 10, 14, 13, 12, 11, 12, 11, 11,  7,
+      16, 15, 16, 13, 15, 13, 15, 10, 16, 15, 14, 12, 14, 12, 12,  7,
+      15, 16, 14, 13, 16, 14, 14, 12, 15, 15, 12, 12, 13, 12, 12,  8,
+      16, 16, 14, 13, 16, 14, 14, 11, 15, 15, 14, 11, 14, 12, 12,  8,
+      16, 16, 15, 12, 16, 14, 15, 10, 16, 16, 13, 12, 14, 13, 12,  7,
+      14, 14, 14, 13, 13, 11, 13, 11, 14, 14, 13, 12, 11, 10, 11,  8,
+      16, 15, 16, 13, 13, 11, 14, 11, 15, 14, 14, 13, 12, 11, 12,  8,
+      15, 15, 16, 14, 14, 10, 14, 10, 16, 15, 15, 13, 14, 10, 12,  8,
+      16, 16, 16, 14, 15, 13, 14, 12, 15, 15, 13, 13, 13, 12, 12,  8,
+      16, 16, 16, 14, 15, 13, 14, 11, 16, 16, 14, 13, 13, 12, 12,  8,
+      16, 16, 16, 14, 16, 12, 15, 11, 16, 15, 15, 13, 14, 12, 12,  8,
+      16, 16, 16, 16, 16, 15, 15, 13, 16, 16, 14, 13, 14, 13, 12,  9,
+      16, 16, 16, 14, 16, 15, 15, 11, 16, 16, 14, 13, 15, 13, 12,  8,
+      16, 16, 16, 14, 16, 14, 14, 10, 16, 16, 15, 13, 14, 12, 12,  7,
+      12, 12, 12, 11, 12, 11, 12, 10, 11, 11, 10,  9,  9,  9,  9,  6,
+      14, 13, 14, 12, 13, 12, 13, 10, 13, 13, 12, 10, 12, 10, 11,  7,
+      16, 14, 16, 13, 15, 13, 16, 12, 15, 14, 14, 12, 14, 12, 13,  8,
+      14, 14, 13, 11, 14, 12, 13, 11, 12, 12, 10, 10, 11, 10, 10,  7,
+      14, 14, 13, 12, 14, 12, 13, 11, 13, 13, 12, 10, 12, 11, 10,  7,
+      16, 15, 15, 12, 16, 14, 15, 11, 16, 14, 13, 11, 14, 12, 12,  8,
+      16, 16, 13, 13, 16, 15, 14, 12, 14, 14, 11, 11, 13, 12, 11,  8,
+      16, 16, 14, 12, 16, 14, 14, 12, 15, 14, 12, 11, 14, 12, 12,  8,
+      16, 15, 14, 11, 16, 15, 15, 11, 16, 15, 13, 11, 14, 13, 12,  8,
+      14, 13, 13, 12, 13, 11, 13, 10, 12, 13, 11, 10, 10, 10, 10,  7,
+      15, 14, 14, 13, 13, 12, 13, 11, 14, 13, 12, 11, 12, 10, 11,  7,
+      16, 15, 16, 14, 15, 12, 15, 11, 16, 14, 14, 12, 14, 11, 12,  8,
+      14, 15, 13, 12, 14, 13, 13, 11, 13, 13, 11, 11, 11, 10, 10,  7,
+      14, 14, 14, 12, 14, 13, 13, 10, 14, 13, 12, 10, 12, 10, 10,  6,
+      16, 15, 15, 13, 16, 13, 15, 11, 15, 14, 13, 11, 13, 11, 11,  7,
+      16, 16, 14, 13, 16, 15, 14, 12, 15, 15, 12, 11, 13, 12, 11,  8,
+      16, 16, 14, 13, 16, 14, 14, 11, 15, 14, 12, 11, 13, 12, 11,  7,
+      16, 16, 15, 12, 16, 14, 14, 11, 15, 15, 13, 11, 14, 12, 11,  6,
+      16, 15, 15, 14, 14, 12, 14, 12, 13, 14, 13, 12, 11, 11, 11,  8,
+      16, 16, 16, 14, 14, 12, 15, 12, 15, 14, 14, 12, 12, 11, 12,  8,
+      16, 16, 16, 15, 14, 12, 15, 12, 16, 15, 14, 13, 13, 11, 12,  8,
+      16, 16, 16, 15, 15, 14, 15, 12, 14, 14, 13, 12, 12, 11, 11,  8,
+      16, 16, 15, 14, 14, 12, 14, 11, 14, 14, 13, 12, 12, 11, 11,  7,
+      16, 16, 16, 14, 15, 12, 14, 11, 15, 15, 14, 12, 13, 11, 12,  7,
+      16, 16, 16, 16, 16, 15, 16, 13, 15, 15, 14, 12, 13, 12, 11,  8,
+      16, 16, 16, 14, 15, 14, 14, 12, 16, 15, 13, 12, 13, 12, 11,  7,
+      16, 16, 16, 13, 16, 13, 14, 10, 16, 15, 14, 11, 13, 11, 11,  6,
+      14, 15, 13, 13, 14, 13, 14, 12, 12, 13, 11, 11, 11, 11, 10,  8,
+      16, 16, 15, 13, 16, 14, 16, 13, 14, 14, 13, 12, 13, 12, 12,  8,
+      16, 16, 16, 14, 16, 14, 16, 13, 16, 14, 15, 13, 15, 13, 13,  9,
+      15, 15, 14, 14, 15, 14, 14, 12, 13, 14, 11, 11, 12, 12, 11,  8,
+      15, 16, 15, 13, 15, 14, 14, 12, 14, 14, 12, 11, 13, 12, 12,  8,
+      16, 16, 16, 13, 16, 15, 15, 13, 16, 15, 14, 11, 15, 12, 13,  8,
+      16, 16, 14, 13, 16, 15, 15, 13, 14, 14, 10, 11, 14, 12, 11,  8,
+      16, 16, 15, 13, 16, 16, 15, 13, 15, 14, 12, 11, 14, 13, 12,  8,
+      16, 16, 15, 13, 16, 15, 16, 12, 16, 14, 13, 10, 15, 13, 12,  7,
+      15, 15, 15, 14, 14, 14, 15, 12, 13, 14, 12, 12, 11, 11, 11,  8,
+      16, 15, 16, 14, 15, 13, 15, 12, 14, 14, 13, 12, 12, 11, 12,  8,
+      16, 16, 16, 15, 16, 14, 16, 13, 16, 15, 14, 12, 14, 11, 13,  8,
+      16, 16, 15, 14, 16, 14, 15, 13, 14, 14, 12, 11, 12, 11, 11,  8,
+      15, 16, 15, 14, 15, 14, 14, 12, 14, 13, 12, 11, 12, 11, 11,  7,
+      16, 16, 16, 14, 16, 13, 16, 12, 15, 14, 13, 11, 13, 11, 12,  7,
+      16, 16, 15, 14, 16, 15, 15, 13, 14, 15, 11, 11, 13, 12, 11,  8,
+      16, 16, 15, 13, 16, 14, 15, 12, 15, 14, 12, 11, 13, 11, 11,  7,
+      16, 16, 15, 13, 16, 14, 16, 12, 15, 14, 13, 10, 13, 11, 11,  6,
+      16, 16, 16, 14, 14, 14, 15, 13, 14, 14, 14, 12, 11, 11, 11,  8,
+      16, 16, 16, 14, 15, 14, 16, 13, 15, 14, 14, 13, 12, 11, 11,  7,
+      16, 16, 16, 16, 15, 13, 16, 12, 15, 15, 14, 12, 13, 10, 12,  7,
+      16, 16, 16, 14, 15, 15, 14, 13, 14, 14, 13, 12, 12, 11, 11,  8,
+      16, 15, 16, 14, 16, 13, 15, 12, 14, 14, 13, 12, 12, 10, 10,  6,
+      16, 15, 16, 14, 16, 13, 16, 11, 16, 14, 13, 11, 13, 10, 11,  6,
+      16, 16, 16, 15, 16, 16, 15, 13, 14, 16, 12, 12, 12, 12, 10,  7,
+      16, 16, 16, 14, 16, 14, 14, 12, 15, 15, 12, 11, 12, 11, 10,  6,
+      16, 16, 16, 13, 16, 13, 15, 10, 15, 14, 13, 10, 13, 10, 10,  4,
+    ], [
+       1,  6,  6,  7,  6,  7,  9,  8,  7,  9,  7,  8,  7,  8,  8,  6,
+       6,  9, 10, 10, 10, 10, 12, 11, 10, 12, 11, 11, 11, 11, 12,  9,
+       9, 10, 13, 11, 13, 12, 14, 13, 14, 14, 14, 14, 14, 14, 14, 12,
+       6, 10,  9, 10, 10, 11, 13, 11, 11, 13, 10, 12, 11, 12, 12,  9,
+       6, 10, 10, 10, 10, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12,  9,
+       9, 11, 13, 12, 13, 14, 15, 13, 14, 16, 14, 14, 14, 14, 15, 12,
+      10, 13, 11, 13, 14, 14, 16, 14, 14, 15, 13, 14, 15, 15, 16, 12,
+       9, 13, 12, 12, 14, 14, 16, 14, 14, 15, 14, 14, 15, 15, 15, 12,
+       8, 11, 12, 11, 13, 14, 15, 13, 13, 15, 14, 14, 13, 15, 15, 11,
+       6, 10, 10, 11,  9, 10, 13, 11, 10, 13, 11, 12, 10, 12, 12,  9,
+       6, 10, 10, 11, 11, 10, 13, 11, 11, 13, 11, 12, 12, 12, 13, 10,
+       9, 12, 13, 13, 13, 12, 16, 13, 14, 15, 14, 14, 15, 14, 15, 12,
+       8, 12, 12, 13, 12, 13, 15, 14, 13, 15, 13, 14, 13, 13, 14, 11,
+       7, 11, 11, 12, 11, 12, 13, 12, 12, 13, 12, 13, 12, 13, 13, 10,
+       9, 12, 13, 13, 13, 13, 16, 13, 13, 15, 14, 14, 14, 15, 15, 12,
+      11, 15, 14, 15, 15, 16, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14,
+      10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 15, 15, 15, 15, 16, 13,
+       9, 12, 13, 13, 13, 14, 16, 14, 13, 15, 14, 14, 14, 16, 15, 12,
+      10, 13, 14, 14, 11, 13, 16, 14, 14, 16, 15, 15, 12, 14, 15, 12,
+      10, 13, 14, 14, 12, 12, 16, 15, 14, 16, 15, 15, 14, 14, 16, 12,
+       9, 12, 13, 14, 13, 11, 16, 13, 14, 15, 13, 14, 14, 14, 15, 12,
+      11, 15, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 13, 14, 14, 13, 14, 16, 15, 14, 16, 16, 16, 14, 15, 16, 13,
+      10, 13, 13, 14, 13, 13, 16, 13, 13, 14, 14, 15, 15, 14, 15, 13,
+      13, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      12, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 12, 13, 14, 13, 13, 14, 13, 13, 14, 13, 14, 14, 14, 15, 12,
+       6, 10, 11, 11, 10, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12, 10,
+       8, 12, 13, 13, 12, 13, 14, 14, 13, 15, 14, 14, 14, 14, 15, 12,
+      12, 14, 16, 15, 15, 15, 16, 15, 16, 16, 16, 16, 16, 16, 16, 14,
+       7, 11, 11, 12, 12, 12, 14, 13, 12, 14, 11, 12, 13, 13, 13, 11,
+       8, 11, 12, 12, 12, 12, 14, 13, 12, 14, 12, 13, 13, 14, 14, 11,
+      11, 13, 14, 14, 14, 14, 16, 15, 15, 16, 15, 15, 16, 16, 16, 13,
+      10, 14, 12, 14, 14, 15, 16, 15, 13, 16, 12, 14, 16, 16, 15, 13,
+      10, 13, 13, 14, 14, 15, 16, 15, 14, 16, 14, 15, 15, 16, 16, 12,
+      10, 13, 14, 13, 14, 14, 16, 15, 14, 16, 15, 15, 14, 16, 16, 13,
+       7, 11, 11, 11, 10, 12, 14, 13, 11, 14, 13, 13, 10, 12, 13, 10,
+       8, 11, 12, 12, 11, 12, 14, 13, 12, 15, 13, 13, 12, 13, 14, 11,
+      11, 13, 14, 14, 14, 14, 16, 15, 14, 16, 15, 16, 16, 16, 16, 14,
+       8, 12, 12, 13, 12, 13, 15, 14, 12, 15, 13, 13, 13, 14, 14, 11,
+       6, 10, 10, 11, 10, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12,  9,
+       9, 12, 13, 13, 13, 13, 14, 13, 13, 15, 14, 14, 14, 14, 14, 12,
+      11, 15, 14, 15, 14, 15, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14,
+       9, 13, 12, 13, 13, 13, 15, 14, 13, 14, 13, 14, 14, 15, 14, 12,
+       9, 12, 12, 12, 12, 13, 14, 13, 13, 14, 13, 13, 13, 13, 14, 11,
+      10, 13, 15, 14, 12, 14, 16, 14, 14, 16, 15, 15, 12, 14, 16, 12,
+      10, 14, 14, 14, 13, 14, 16, 15, 14, 16, 16, 16, 13, 14, 16, 13,
+      11, 13, 14, 14, 14, 13, 16, 14, 14, 16, 15, 15, 15, 15, 16, 13,
+      11, 15, 15, 15, 14, 15, 16, 16, 15, 16, 16, 16, 14, 16, 16, 13,
+       9, 13, 13, 13, 12, 13, 15, 14, 13, 15, 14, 14, 13, 14, 15, 11,
+       9, 12, 12, 13, 12, 12, 14, 13, 13, 14, 13, 14, 14, 14, 14, 11,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      11, 14, 14, 15, 15, 14, 16, 16, 14, 16, 14, 15, 15, 16, 16, 12,
+       9, 12, 12, 13, 12, 12, 14, 12, 12, 14, 13, 13, 13, 13, 14, 11,
+      11, 14, 14, 16, 14, 16, 16, 16, 13, 16, 14, 16, 14, 16, 16, 13,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 15, 14, 16, 14, 15, 16, 16, 15, 16, 14, 15, 16, 16, 16, 13,
+      11, 15, 14, 16, 15, 16, 16, 16, 15, 16, 15, 16, 16, 16, 16, 14,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      11, 14, 13, 14, 15, 14, 16, 15, 14, 16, 12, 14, 16, 16, 15, 13,
+      11, 14, 14, 16, 14, 15, 16, 16, 15, 16, 14, 15, 16, 16, 16, 14,
+      12, 14, 14, 15, 14, 16, 16, 15, 14, 16, 15, 15, 15, 16, 16, 13,
+      11, 14, 15, 15, 13, 15, 16, 16, 14, 16, 16, 16, 12, 15, 15, 13,
+      11, 15, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      11, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+      10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 14, 15, 14, 14, 15, 12,
+      12, 15, 14, 16, 14, 15, 16, 15, 15, 16, 15, 15, 16, 15, 16, 13,
+      12, 16, 14, 16, 15, 16, 16, 16, 16, 16, 14, 15, 16, 16, 16, 14,
+      10, 13, 13, 14, 14, 13, 16, 14, 13, 16, 13, 14, 15, 15, 15, 12,
+      10, 13, 13, 14, 13, 13, 16, 14, 14, 15, 14, 14, 14, 14, 15, 12,
+      10, 14, 15, 14, 13, 15, 16, 15, 14, 16, 16, 16, 11, 14, 16, 12,
+      11, 14, 14, 16, 14, 15, 16, 15, 15, 16, 16, 16, 13, 15, 16, 13,
+      12, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13,
+      12, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13,
+      10, 13, 14, 14, 13, 14, 16, 14, 13, 16, 15, 14, 12, 14, 16, 11,
+      10, 13, 13, 14, 13, 14, 16, 14, 14, 15, 14, 14, 13, 14, 14, 11,
+      13, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      11, 13, 14, 15, 14, 14, 16, 15, 14, 16, 14, 15, 14, 15, 16, 12,
+       8, 11, 11, 11, 11, 12, 13, 12, 11, 13, 11, 12, 11, 12, 12,  9,
+    ],
+  ], [
+    [
+       8,  8,  8,  7,  8,  7,  8,  6,  8,  8,  7,  6,  7,  6,  6,  4,
+      11, 10, 11,  9, 11,  9, 11,  8, 11, 10, 10,  9, 10,  8,  9,  6,
+      13, 11, 13, 10, 12, 10, 13,  9, 13, 12, 13, 10, 12, 10, 11,  7,
+      11, 11, 10,  9, 11, 10, 11,  9, 10, 11,  9,  8, 10,  9,  9,  6,
+      12, 12, 11,  9, 12, 11, 12,  9, 12, 12, 11,  9, 11, 10, 10,  7,
+      14, 13, 13, 10, 15, 12, 13, 10, 15, 13, 13, 10, 13, 12, 12,  8,
+      13, 13, 11, 10, 14, 13, 12, 10, 13, 13, 10, 10, 12, 11, 10,  8,
+      15, 14, 13, 10, 14, 13, 13, 10, 14, 13, 12, 10, 13, 12, 11,  8,
+      14, 14, 13, 10, 16, 13, 13, 10, 15, 14, 13, 10, 13, 12, 12,  8,
+      11, 11, 11, 10, 10,  9, 10,  9, 10, 10, 10,  9,  9,  8,  9,  6,
+      12, 12, 12, 11, 11,  9, 12,  9, 12, 12, 11, 10, 11,  9, 10,  7,
+      14, 13, 14, 12, 13, 10, 13, 10, 15, 13, 14, 12, 12, 10, 12,  8,
+      13, 13, 12, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10,  7,
+      14, 13, 13, 11, 13, 12, 12, 10, 13, 13, 12, 11, 12, 10, 10,  7,
+      16, 15, 15, 12, 14, 12, 13, 10, 15, 14, 13, 12, 13, 12, 12,  8,
+      15, 15, 13, 13, 14, 14, 14, 12, 14, 14, 12, 11, 13, 12, 11,  8,
+      15, 16, 14, 12, 15, 14, 13, 11, 15, 15, 13, 12, 13, 12, 11,  8,
+      16, 15, 15, 12, 16, 14, 14, 10, 15, 15, 14, 12, 14, 12, 12,  8,
+      13, 13, 13, 13, 11, 10, 12, 10, 12, 13, 12, 11, 10, 10, 10,  8,
+      14, 13, 14, 13, 12, 10, 13, 10, 14, 14, 13, 12, 12, 10, 11,  8,
+      15, 14, 16, 14, 13, 10, 14, 10, 16, 14, 14, 13, 13, 10, 12,  8,
+      15, 15, 14, 14, 14, 13, 13, 12, 14, 14, 13, 12, 12, 11, 11,  9,
+      15, 15, 15, 14, 14, 12, 14, 11, 15, 14, 13, 13, 13, 11, 11,  8,
+      16, 15, 16, 14, 15, 12, 14, 11, 16, 16, 15, 13, 14, 12, 12,  8,
+      16, 16, 16, 14, 15, 14, 14, 12, 15, 15, 14, 13, 13, 12, 11,  9,
+      16, 16, 15, 15, 16, 14, 14, 11, 16, 16, 14, 13, 14, 12, 12,  8,
+      16, 16, 16, 13, 15, 13, 14, 10, 16, 16, 15, 13, 14, 12, 12,  8,
+      11, 11, 11, 10, 11, 10, 11,  9, 10, 10,  9,  8,  9,  9,  9,  6,
+      12, 12, 13, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10,  7,
+      15, 13, 15, 12, 14, 13, 14, 11, 14, 13, 13, 11, 13, 11, 12,  8,
+      12, 13, 12, 11, 13, 11, 12, 10, 11, 12, 10,  9, 11, 10, 10,  7,
+      14, 13, 13, 11, 14, 12, 13, 11, 12, 12, 11, 10, 12, 11, 10,  7,
+      15, 14, 15, 12, 15, 13, 15, 11, 15, 14, 13, 11, 13, 12, 12,  8,
+      14, 14, 13, 12, 15, 14, 13, 12, 13, 13, 11, 10, 13, 12, 11,  8,
+      16, 15, 13, 12, 15, 14, 14, 12, 14, 14, 12, 11, 14, 12, 11,  8,
+      16, 15, 14, 12, 16, 15, 15, 11, 15, 14, 13, 11, 14, 13, 12,  8,
+      12, 12, 12, 11, 12, 11, 12, 10, 11, 11, 11, 10, 10,  9,  9,  7,
+      13, 13, 14, 12, 13, 11, 13, 11, 13, 12, 12, 11, 11, 10, 10,  7,
+      15, 14, 16, 13, 14, 12, 14, 11, 14, 14, 14, 12, 13, 11, 12,  8,
+      13, 13, 13, 12, 13, 12, 13, 11, 12, 12, 11, 10, 11, 10, 10,  7,
+      14, 14, 13, 12, 13, 12, 13, 10, 13, 13, 11, 10, 12, 10, 10,  7,
+      16, 15, 15, 13, 15, 12, 14, 11, 15, 14, 13, 11, 13, 11, 11,  7,
+      15, 16, 14, 13, 15, 14, 14, 12, 14, 14, 12, 11, 13, 12, 11,  8,
+      16, 15, 14, 13, 15, 14, 14, 11, 14, 14, 12, 11, 13, 12, 11,  7,
+      16, 15, 15, 12, 16, 14, 14, 11, 15, 14, 13, 11, 14, 12, 11,  7,
+      14, 15, 14, 14, 13, 12, 13, 12, 13, 13, 12, 12, 11, 10, 11,  8,
+      15, 15, 15, 14, 13, 12, 14, 12, 14, 14, 13, 12, 12, 11, 11,  8,
+      16, 15, 16, 14, 14, 12, 15, 12, 16, 14, 14, 13, 13, 11, 12,  8,
+      15, 15, 15, 14, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11,  8,
+      15, 15, 15, 14, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11,  7,
+      16, 15, 16, 14, 15, 12, 15, 11, 15, 14, 14, 12, 13, 11, 12,  7,
+      16, 16, 16, 15, 16, 15, 14, 13, 15, 15, 13, 12, 13, 12, 11,  9,
+      16, 16, 16, 14, 15, 14, 14, 12, 15, 15, 13, 12, 14, 12, 11,  8,
+      16, 16, 16, 14, 16, 14, 14, 11, 15, 15, 14, 12, 14, 12, 11,  7,
+      13, 13, 13, 12, 13, 12, 13, 11, 11, 12, 11, 10, 10, 10, 10,  8,
+      15, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 13, 11, 11,  8,
+      16, 15, 16, 14, 16, 14, 16, 13, 15, 14, 14, 12, 14, 12, 13,  9,
+      14, 15, 13, 13, 14, 13, 14, 12, 12, 13, 11, 11, 12, 11, 11,  8,
+      15, 15, 14, 13, 15, 14, 14, 12, 13, 13, 12, 11, 13, 12, 11,  8,
+      16, 16, 16, 13, 16, 15, 16, 13, 15, 14, 14, 12, 14, 13, 13,  9,
+      14, 15, 13, 13, 16, 15, 15, 13, 13, 14, 11, 11, 13, 12, 11,  9,
+      16, 16, 14, 13, 16, 15, 16, 13, 14, 14, 12, 11, 14, 13, 12,  8,
+      16, 16, 15, 12, 16, 15, 15, 12, 15, 14, 13, 11, 14, 13, 12,  8,
+      14, 14, 14, 13, 14, 13, 14, 12, 12, 13, 12, 11, 11, 11, 11,  8,
+      15, 15, 15, 14, 14, 13, 15, 12, 14, 13, 13, 12, 12, 11, 11,  8,
+      16, 16, 16, 15, 15, 14, 16, 13, 15, 14, 14, 12, 14, 12, 12,  9,
+      15, 15, 14, 14, 14, 14, 14, 13, 13, 14, 12, 11, 12, 11, 11,  8,
+      15, 15, 15, 13, 15, 14, 14, 12, 13, 13, 12, 11, 12, 11, 11,  7,
+      16, 15, 16, 14, 16, 14, 15, 12, 15, 14, 14, 12, 13, 12, 12,  8,
+      16, 16, 15, 14, 16, 15, 15, 13, 14, 14, 12, 11, 13, 12, 11,  8,
+      16, 16, 15, 13, 16, 14, 14, 12, 14, 15, 12, 11, 13, 12, 11,  7,
+      16, 16, 16, 13, 16, 15, 15, 12, 15, 14, 13, 11, 14, 12, 11,  7,
+      15, 15, 15, 14, 13, 13, 14, 13, 13, 14, 13, 12, 11, 11, 11,  8,
+      16, 16, 16, 14, 15, 13, 15, 12, 14, 14, 14, 13, 12, 11, 12,  8,
+      16, 16, 16, 14, 15, 13, 15, 12, 15, 14, 14, 12, 13, 11, 12,  8,
+      15, 16, 16, 14, 15, 14, 15, 13, 14, 14, 12, 12, 11, 11, 11,  8,
+      16, 15, 15, 14, 15, 14, 14, 12, 14, 14, 13, 12, 12, 11, 11,  7,
+      16, 16, 16, 13, 15, 13, 15, 12, 15, 14, 14, 12, 13, 11, 11,  7,
+      16, 16, 16, 15, 15, 16, 15, 13, 14, 14, 12, 12, 12, 12, 11,  8,
+      16, 16, 16, 14, 16, 14, 14, 12, 15, 15, 13, 11, 12, 11, 10,  7,
+      16, 16, 15, 13, 16, 14, 14, 11, 15, 14, 13, 10, 13, 11, 10,  5,
+    ], [
+       1,  6,  6,  7,  6,  7,  9,  7,  6,  9,  7,  8,  7,  8,  8,  5,
+       5,  8, 10, 10, 10, 10, 12, 11, 11, 12, 11, 11, 11, 12, 12,  9,
+       9, 10, 12, 11, 13, 12, 15, 13, 14, 15, 15, 14, 14, 15, 15, 12,
+       6, 10,  9, 10, 10, 11, 13, 12, 11, 13, 11, 12, 12, 12, 12, 10,
+       6, 10, 10, 10, 11, 11, 13, 11, 11, 13, 12, 12, 11, 12, 12, 10,
+       9, 12, 13, 12, 13, 13, 16, 13, 14, 16, 15, 14, 14, 15, 16, 12,
+       9, 13, 11, 13, 14, 14, 16, 15, 14, 16, 13, 15, 15, 15, 15, 12,
+       9, 13, 12, 13, 14, 15, 16, 15, 14, 16, 15, 15, 15, 15, 16, 12,
+       8, 12, 12, 11, 13, 14, 15, 13, 13, 15, 14, 14, 14, 14, 14, 12,
+       6, 10, 10, 11,  9, 10, 13, 11, 11, 13, 12, 12, 10, 12, 12,  9,
+       6, 10, 11, 11, 11, 10, 13, 12, 11, 13, 12, 12, 12, 12, 13, 10,
+       9, 12, 13, 13, 13, 12, 16, 13, 14, 16, 14, 15, 16, 14, 15, 12,
+       8, 12, 13, 13, 13, 13, 16, 14, 13, 16, 13, 14, 14, 14, 14, 12,
+       7, 11, 11, 12, 11, 12, 14, 13, 12, 14, 13, 13, 12, 13, 13, 11,
+       9, 12, 13, 13, 13, 13, 15, 14, 14, 16, 16, 15, 15, 15, 16, 12,
+      11, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 14, 14, 15, 15, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13,
+       9, 13, 13, 13, 14, 14, 16, 14, 14, 16, 15, 14, 14, 16, 16, 13,
+       9, 13, 14, 14, 11, 13, 16, 14, 13, 16, 15, 16, 13, 14, 15, 12,
+      10, 13, 14, 15, 13, 12, 16, 14, 14, 16, 15, 15, 14, 14, 16, 13,
+       9, 12, 13, 14, 12, 11, 15, 13, 13, 15, 13, 14, 15, 14, 16, 12,
+      11, 15, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13,
+      11, 14, 14, 15, 13, 14, 16, 15, 15, 16, 16, 16, 16, 16, 16, 13,
+      10, 12, 13, 14, 13, 13, 16, 14, 14, 14, 14, 16, 15, 14, 16, 13,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       9, 12, 13, 14, 13, 13, 16, 13, 13, 15, 15, 16, 15, 15, 16, 12,
+       6, 11, 11, 12, 10, 12, 13, 12, 11, 13, 11, 12, 11, 12, 13, 10,
+       9, 12, 13, 13, 13, 13, 16, 14, 14, 15, 14, 14, 14, 14, 14, 12,
+      12, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       7, 11, 11, 12, 12, 12, 14, 13, 12, 14, 11, 13, 13, 13, 13, 11,
+       8, 12, 12, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13, 14, 14, 11,
+      11, 14, 14, 15, 16, 15, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13,
+      10, 14, 12, 14, 15, 15, 16, 16, 14, 16, 12, 15, 16, 16, 16, 13,
+      11, 14, 13, 15, 15, 15, 16, 16, 14, 16, 14, 14, 16, 16, 16, 13,
+      11, 14, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 13,
+       7, 11, 12, 11, 10, 12, 14, 13, 12, 14, 13, 13, 10, 12, 13, 10,
+       8, 12, 12, 13, 12, 12, 15, 13, 13, 14, 13, 13, 13, 13, 14, 11,
+      11, 13, 15, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+       9, 12, 13, 13, 13, 13, 15, 14, 13, 15, 13, 14, 13, 14, 14, 12,
+       7, 11, 11, 11, 11, 11, 13, 12, 11, 13, 11, 12, 11, 12, 12, 10,
+       9, 12, 13, 13, 13, 13, 16, 13, 14, 16, 15, 14, 14, 14, 16, 12,
+      12, 14, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14,
+      10, 13, 13, 14, 14, 14, 16, 15, 14, 16, 14, 14, 16, 15, 15, 12,
+       9, 12, 13, 13, 13, 15, 16, 14, 13, 16, 14, 13, 13, 14, 14, 11,
+      10, 14, 15, 14, 12, 14, 16, 15, 13, 16, 16, 16, 12, 14, 16, 12,
+      11, 14, 14, 14, 14, 14, 16, 15, 15, 16, 16, 16, 14, 15, 16, 13,
+      11, 14, 14, 16, 14, 13, 16, 15, 14, 16, 15, 16, 15, 15, 16, 13,
+      12, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14,
+      10, 13, 14, 14, 13, 14, 16, 14, 13, 16, 15, 15, 13, 14, 14, 12,
+       9, 12, 13, 14, 13, 12, 16, 14, 13, 16, 14, 14, 14, 14, 15, 12,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+       9, 12, 13, 13, 13, 13, 14, 13, 12, 15, 14, 14, 14, 14, 14, 11,
+      11, 14, 14, 16, 14, 16, 16, 16, 13, 16, 14, 16, 14, 16, 16, 13,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 14, 14, 16, 16, 15, 16, 16, 15, 16, 14, 16, 16, 16, 16, 14,
+      12, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 14, 12, 15, 15, 15, 16, 16, 14, 16, 12, 14, 16, 16, 15, 14,
+      12, 15, 14, 16, 16, 16, 16, 16, 15, 16, 14, 16, 16, 16, 16, 14,
+      12, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14,
+      11, 15, 15, 16, 14, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      11, 15, 14, 16, 14, 14, 16, 15, 14, 16, 15, 16, 15, 16, 16, 12,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+      12, 16, 15, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 14,
+      10, 14, 13, 14, 15, 14, 16, 15, 14, 16, 13, 16, 16, 16, 15, 13,
+      10, 14, 14, 14, 13, 14, 16, 15, 15, 16, 14, 14, 14, 16, 16, 12,
+      10, 14, 15, 14, 13, 16, 16, 15, 13, 16, 16, 16, 12, 14, 16, 12,
+      11, 16, 16, 16, 14, 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13,
+      12, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14,
+      11, 14, 14, 14, 14, 15, 16, 14, 14, 16, 16, 16, 13, 15, 15, 12,
+      10, 14, 13, 14, 14, 14, 16, 15, 14, 16, 15, 15, 14, 14, 16, 12,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      12, 14, 14, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 13,
+       8, 11, 11, 12, 12, 12, 13, 12, 11, 13, 12, 12, 12, 13, 12, 10,
+    ],
+  ], [
+    [
+       5,  6,  6,  6,  6,  6,  7,  6,  6,  7,  6,  6,  6,  6,  6,  4,
+       9,  9,  9,  8,  9,  8, 10,  8, 10, 10,  9,  9,  9,  8,  9,  6,
+      11, 10, 12, 10, 11, 10, 12,  9, 12, 11, 11, 10, 11, 10, 11,  8,
+       9, 10,  9,  8, 10, 10, 10,  9,  9, 10,  8,  8,  9,  9,  8,  7,
+      10, 11, 10,  9, 11, 11, 11,  9, 11, 11, 10,  9, 10, 10, 10,  7,
+      13, 12, 12, 10, 13, 12, 13, 10, 13, 12, 12, 11, 13, 12, 11,  9,
+      11, 12, 10, 10, 12, 12, 11, 10, 11, 12, 10, 10, 11, 11, 10,  8,
+      12, 12, 11, 10, 13, 13, 13, 10, 13, 13, 12, 11, 13, 12, 11,  9,
+      12, 12, 12, 10, 13, 13, 13, 10, 13, 13, 12, 10, 13, 12, 12,  9,
+       9,  9, 10, 10,  9,  8, 10,  9,  9, 10,  9,  9,  8,  8,  9,  6,
+      10, 11, 11, 11, 10,  9, 11,  9, 11, 11, 11, 10, 10,  9, 10,  7,
+      12, 12, 13, 12, 12, 10, 13, 10, 13, 13, 13, 12, 12, 11, 11,  9,
+      11, 12, 11, 11, 11, 11, 11, 10, 11, 12, 10, 10, 10, 10, 10,  8,
+      12, 12, 12, 11, 12, 11, 11, 10, 12, 12, 11, 11, 11, 11, 10,  8,
+      14, 13, 13, 12, 13, 12, 13, 10, 14, 14, 13, 12, 13, 12, 12,  9,
+      13, 14, 13, 12, 13, 13, 13, 12, 13, 13, 12, 12, 12, 12, 11,  9,
+      14, 14, 13, 12, 13, 13, 13, 11, 14, 14, 13, 12, 13, 12, 12,  9,
+      14, 15, 14, 12, 15, 13, 13, 11, 15, 14, 14, 12, 14, 13, 12,  9,
+      11, 11, 12, 12, 10, 10, 12, 11, 11, 12, 11, 11, 10, 10, 10,  8,
+      12, 12, 14, 13, 11, 10, 12, 11, 13, 13, 13, 12, 12, 10, 11,  9,
+      13, 13, 14, 14, 12, 10, 13, 11, 14, 14, 14, 13, 12, 11, 12,  9,
+      13, 13, 13, 13, 12, 13, 13, 12, 13, 14, 12, 12, 12, 12, 11,  9,
+      13, 14, 14, 13, 13, 12, 13, 11, 14, 14, 13, 12, 13, 12, 12,  9,
+      14, 14, 14, 14, 14, 12, 13, 11, 15, 15, 15, 13, 14, 12, 12,  9,
+      14, 15, 15, 13, 14, 14, 13, 12, 13, 14, 13, 13, 12, 12, 11, 10,
+      16, 16, 15, 14, 15, 14, 13, 11, 15, 15, 14, 13, 13, 13, 12,  9,
+      15, 15, 15, 13, 14, 13, 13, 11, 15, 15, 15, 13, 14, 13, 12,  9,
+       8,  9,  9,  9,  9,  9, 10,  9,  8, 10,  9,  9,  8,  8,  9,  7,
+      11, 11, 11, 11, 11, 11, 12, 10, 11, 11, 11, 10, 10, 10, 10,  8,
+      13, 13, 14, 12, 13, 12, 14, 11, 13, 13, 13, 12, 13, 11, 12,  9,
+      10, 11, 10, 11, 11, 11, 12, 10, 10, 11, 10, 10, 10, 10, 10,  8,
+      12, 12, 12, 11, 12, 12, 12, 11, 11, 12, 11, 10, 11, 11, 10,  8,
+      14, 13, 14, 12, 14, 13, 14, 12, 14, 13, 13, 11, 13, 12, 12,  9,
+      12, 13, 12, 12, 13, 13, 13, 12, 12, 13, 11, 11, 12, 12, 11,  9,
+      13, 14, 13, 12, 14, 14, 14, 12, 14, 13, 12, 11, 13, 12, 12,  9,
+      14, 14, 13, 12, 15, 14, 15, 12, 14, 14, 13, 11, 13, 13, 12,  9,
+      10, 11, 11, 11, 10, 10, 12, 10, 10, 11, 10, 10,  9,  9, 10,  7,
+      12, 12, 13, 12, 12, 11, 12, 11, 12, 12, 12, 11, 11, 10, 10,  8,
+      14, 13, 14, 13, 14, 12, 13, 12, 14, 13, 14, 12, 13, 11, 12,  9,
+      12, 13, 12, 12, 12, 12, 12, 11, 11, 12, 11, 10, 10, 10, 10,  8,
+      12, 12, 12, 12, 12, 12, 12, 11, 12, 12, 11, 10, 11, 10, 10,  7,
+      14, 14, 14, 12, 14, 12, 14, 11, 14, 13, 13, 11, 13, 11, 11,  8,
+      13, 15, 13, 13, 14, 14, 14, 12, 13, 14, 12, 12, 12, 12, 11,  9,
+      14, 15, 13, 12, 14, 13, 13, 11, 13, 13, 12, 11, 13, 12, 11,  8,
+      15, 15, 15, 12, 15, 14, 14, 11, 14, 14, 13, 11, 13, 12, 12,  8,
+      12, 13, 13, 13, 12, 12, 13, 12, 12, 13, 12, 12, 11, 11, 11,  9,
+      13, 14, 15, 14, 13, 12, 14, 12, 13, 13, 14, 12, 12, 11, 12,  9,
+      14, 14, 15, 14, 14, 12, 14, 12, 14, 14, 14, 13, 13, 11, 12,  9,
+      13, 14, 14, 14, 13, 13, 14, 13, 13, 13, 12, 12, 12, 12, 11,  9,
+      14, 14, 14, 13, 13, 13, 13, 12, 13, 14, 13, 12, 12, 11, 11,  8,
+      15, 14, 15, 14, 14, 13, 14, 11, 15, 14, 14, 12, 13, 11, 12,  8,
+      14, 15, 14, 14, 15, 14, 14, 13, 14, 15, 13, 13, 12, 12, 11, 10,
+      16, 15, 14, 14, 14, 14, 13, 12, 14, 14, 13, 12, 13, 12, 11,  9,
+      15, 15, 15, 14, 16, 14, 14, 11, 15, 15, 14, 12, 13, 12, 11,  8,
+      11, 12, 11, 12, 12, 12, 12, 11, 10, 11, 10, 10, 10, 10, 10,  8,
+      13, 13, 13, 13, 13, 13, 14, 12, 12, 12, 12, 12, 12, 11, 12,  9,
+      14, 14, 14, 13, 15, 13, 15, 13, 14, 14, 14, 12, 14, 12, 13, 10,
+      12, 13, 12, 13, 13, 13, 13, 12, 11, 12, 11, 11, 12, 11, 11,  9,
+      14, 14, 13, 13, 14, 14, 14, 12, 12, 13, 12, 11, 13, 12, 12,  9,
+      14, 14, 15, 13, 15, 15, 15, 13, 15, 13, 13, 12, 14, 12, 13, 10,
+      13, 15, 12, 13, 14, 14, 14, 13, 12, 13, 11, 11, 13, 12, 11, 10,
+      14, 15, 14, 13, 15, 14, 15, 13, 14, 14, 12, 11, 13, 13, 12,  9,
+      14, 15, 14, 13, 15, 14, 15, 13, 14, 14, 13, 11, 14, 13, 12,  9,
+      12, 13, 13, 13, 12, 13, 13, 12, 11, 12, 12, 11, 11, 11, 11,  9,
+      13, 14, 14, 13, 14, 13, 14, 12, 13, 13, 13, 12, 12, 11, 11,  9,
+      15, 15, 16, 14, 15, 14, 14, 13, 15, 14, 14, 13, 13, 12, 13, 10,
+      13, 14, 14, 13, 13, 14, 14, 13, 12, 13, 12, 12, 11, 11, 11,  9,
+      14, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 12, 11, 11,  8,
+      15, 15, 15, 13, 15, 14, 14, 12, 14, 13, 13, 12, 13, 12, 12,  9,
+      14, 15, 14, 14, 15, 15, 14, 13, 13, 14, 12, 12, 13, 12, 12,  9,
+      15, 15, 14, 13, 15, 14, 14, 13, 14, 14, 12, 11, 13, 12, 11,  8,
+      15, 16, 14, 13, 15, 15, 15, 12, 14, 14, 13, 11, 14, 12, 12,  8,
+      12, 14, 13, 13, 13, 13, 14, 12, 12, 13, 12, 12, 10, 11, 11,  9,
+      14, 15, 15, 14, 13, 13, 15, 13, 13, 14, 14, 12, 12, 11, 12,  9,
+      15, 15, 16, 14, 14, 13, 15, 13, 14, 14, 14, 13, 13, 11, 12,  9,
+      14, 15, 14, 14, 14, 14, 14, 13, 13, 14, 13, 12, 12, 12, 11,  9,
+      14, 15, 15, 14, 14, 14, 14, 12, 13, 14, 13, 12, 12, 11, 11,  8,
+      15, 15, 15, 14, 14, 13, 15, 12, 15, 14, 14, 12, 13, 11, 11,  8,
+      14, 16, 14, 14, 14, 15, 14, 13, 13, 14, 12, 12, 12, 12, 11,  9,
+      15, 15, 15, 14, 15, 14, 14, 12, 14, 14, 13, 12, 12, 11, 11,  8,
+      15, 15, 14, 13, 15, 13, 14, 12, 14, 14, 13, 11, 13, 11, 11,  7,
+    ], [
+       1,  5,  6,  7,  6,  7,  9,  8,  6,  9,  8,  8,  7,  8,  8,  6,
+       5,  8, 10, 10, 10, 11, 13, 12, 11, 13, 12, 12, 12, 12, 13, 10,
+       8, 10, 13, 12, 13, 13, 16, 14, 14, 16, 16, 14, 16, 16, 16, 12,
+       5, 10,  9, 11, 11, 12, 13, 12, 11, 13, 11, 12, 12, 12, 13, 10,
+       6, 10, 11, 11, 11, 12, 14, 12, 11, 13, 13, 13, 12, 13, 13, 11,
+       8, 12, 13, 12, 14, 14, 16, 14, 14, 16, 16, 16, 16, 16, 16, 13,
+       9, 13, 11, 14, 14, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13,
+       9, 13, 13, 13, 14, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 14,
+       8, 12, 13, 12, 13, 14, 16, 14, 14, 16, 16, 16, 14, 16, 16, 13,
+       5, 10, 11, 12,  9, 11, 13, 12, 11, 13, 13, 13, 11, 12, 13, 10,
+       6, 10, 11, 12, 11, 11, 14, 13, 12, 14, 12, 13, 13, 13, 13, 11,
+       9, 12, 14, 15, 13, 13, 16, 16, 14, 16, 16, 16, 16, 16, 16, 13,
+       8, 13, 13, 14, 13, 14, 16, 16, 14, 16, 14, 16, 14, 16, 14, 13,
+       7, 11, 12, 13, 12, 12, 14, 13, 12, 14, 13, 14, 13, 14, 14, 12,
+       9, 13, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 15, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       9, 13, 14, 14, 14, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14,
+       9, 13, 14, 15, 11, 13, 16, 14, 14, 16, 16, 16, 13, 14, 16, 13,
+       9, 13, 14, 16, 13, 13, 16, 16, 14, 16, 16, 16, 16, 15, 16, 14,
+       8, 12, 13, 16, 13, 12, 16, 14, 13, 16, 14, 16, 16, 16, 16, 13,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 14, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       9, 13, 16, 16, 14, 14, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 13, 14, 15, 14, 14, 16, 14, 13, 16, 16, 16, 14, 16, 16, 14,
+       6, 11, 11, 12, 11, 12, 14, 13, 11, 14, 12, 13, 12, 13, 13, 11,
+       9, 13, 13, 14, 13, 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 13,
+      11, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       7, 11, 11, 13, 12, 13, 16, 14, 12, 16, 12, 14, 14, 14, 14, 12,
+       8, 12, 12, 13, 12, 14, 16, 14, 13, 16, 14, 14, 14, 14, 14, 12,
+      11, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 14, 13, 16, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16,
+      10, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       7, 11, 12, 12, 11, 13, 16, 14, 12, 15, 14, 14, 11, 13, 13, 12,
+       8, 12, 12, 13, 13, 13, 16, 14, 13, 16, 13, 15, 13, 14, 14, 12,
+      11, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       8, 12, 13, 14, 13, 14, 16, 16, 14, 16, 14, 16, 14, 16, 15, 13,
+       6, 11, 11, 12, 11, 12, 13, 13, 11, 13, 12, 13, 12, 13, 13, 11,
+       9, 13, 14, 14, 14, 14, 16, 14, 14, 16, 16, 16, 16, 16, 14, 13,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 14, 13, 14, 14, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13,
+       9, 13, 14, 13, 13, 16, 16, 14, 13, 16, 16, 16, 13, 16, 14, 13,
+      10, 14, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 13, 14, 16, 14,
+      11, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 14, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 14, 14, 14, 14, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 13,
+       9, 13, 13, 16, 14, 14, 16, 16, 14, 16, 14, 16, 16, 16, 16, 13,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 13, 14, 14, 13, 16, 16, 14, 13, 16, 14, 16, 14, 14, 16, 12,
+      10, 14, 14, 16, 16, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 14,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 14, 13, 16, 16, 16, 16, 16, 14, 16, 12, 16, 16, 16, 16, 14,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 14,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+      11, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 13,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 15, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 14,
+      10, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+      10, 14, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 14,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16,
+      11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 15, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 13,
+      10, 15, 14, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+       8, 12, 12, 13, 12, 14, 14, 14, 12, 16, 13, 14, 12, 14, 14, 11,
+    ],
+  ],
+];
+
+const RV34_INTRA_CBP: &'static [[[u8; 16]; 8]; 5] = &[
+  [
+    [ 0,  3,  3,  4,  3,  5,  5,  5,  2,  5,  4,  6,  4,  6,  6,  6, ],
+    [ 0,  2,  3,  4,  2,  5,  6,  7,  3,  6,  5,  7,  4,  7,  8,  8, ],
+    [ 0,  3,  4,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  3, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  6,  3,  5,  6,  5, ],
+    [ 0,  4,  4,  4,  4,  5,  5,  4,  4,  5,  4,  5,  4,  4,  4,  2, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  6,  6,  5,  6,  5,  6,  4,  6,  6,  5,  4,  4,  4,  4,  1, ],
+    [ 0,  4,  4,  4,  4,  5,  5,  4,  4,  5,  5,  4,  4,  4,  4,  2, ],
+  ], [
+    [ 0,  4,  3,  4,  3,  4,  5,  4,  3,  5,  4,  5,  3,  5,  5,  5, ],
+    [ 0,  2,  3,  4,  2,  5,  6,  7,  3,  6,  5,  7,  4,  7,  8,  8, ],
+    [ 0,  4,  4,  4,  4,  4,  5,  4,  4,  5,  4,  4,  3,  4,  4,  3, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  6,  3,  5,  6,  5, ],
+    [ 0,  4,  4,  4,  4,  4,  5,  4,  4,  5,  5,  5,  4,  4,  4,  2, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  5,  6,  5,  5,  5,  6,  4,  6,  6,  5,  4,  5,  4,  4,  1, ],
+    [ 0,  4,  4,  4,  4,  4,  5,  4,  4,  5,  5,  4,  4,  4,  5,  2, ],
+  ], [
+    [ 0,  3,  3,  4,  3,  4,  4,  5,  3,  5,  4,  5,  4,  5,  5,  5, ],
+    [ 0,  2,  3,  4,  2,  4,  6,  7,  3,  6,  5,  7,  5,  7,  8,  8, ],
+    [ 0,  4,  4,  4,  4,  4,  5,  4,  3,  5,  4,  4,  4,  4,  4,  3, ],
+    [ 0,  3,  3,  4,  3,  3,  6,  6,  3,  6,  4,  6,  3,  6,  6,  5, ],
+    [ 0,  4,  4,  4,  3,  4,  5,  4,  4,  5,  4,  4,  4,  4,  4,  3, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  5,  5,  5,  5,  5,  6,  4,  5,  6,  5,  5,  5,  4,  4,  1, ],
+    [ 0,  4,  4,  4,  4,  4,  6,  4,  4,  6,  5,  4,  4,  4,  4,  2, ],
+  ], [
+    [ 0,  3,  3,  4,  3,  4,  4,  5,  3,  5,  4,  5,  4,  5,  5,  5, ],
+    [ 0,  2,  3,  4,  2,  4,  7,  6,  3,  7,  5,  7,  5,  7,  7,  7, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  3,  3,  3,  3,  4,  6,  6,  3,  6,  4,  6,  3,  6,  6,  5, ],
+    [ 0,  3,  4,  4,  3,  4,  5,  4,  4,  5,  4,  5,  4,  5,  4,  3, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  4,  5,  4,  4,  4,  5,  4,  4,  5,  5,  4,  4,  4,  4,  2, ],
+    [ 0,  4,  4,  4,  4,  5,  5,  4,  4,  5,  5,  4,  4,  4,  4,  2, ],
+  ], [
+    [ 0,  3,  3,  4,  3,  4,  5,  6,  2,  5,  4,  7,  4,  6,  6,  7, ],
+    [ 0,  2,  3,  4,  2,  4,  6,  7,  3,  7,  5,  7,  5,  7,  7,  7, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  2,  3,  4,  3,  4,  6,  5,  3,  6,  4,  6,  4,  6,  6,  6, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  3,  3,  4,  3,  4,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4, ],
+    [ 0,  4,  4,  4,  4,  5,  5,  4,  4,  5,  5,  4,  4,  4,  4,  2, ],
+    [ 0,  3,  4,  4,  4,  4,  5,  4,  4,  5,  4,  4,  4,  4,  4,  3, ],
+  ],
+];
+
+const RV34_INTRA_FIRSTPAT: &'static [[[u8; 864]; 4]; 5] = &[
+  [
+    [
+       0, 10,  5, 10,  7, 12,  9, 11,  8, 13,  9, 12, 10, 13, 11, 12,
+      16, 16, 14, 15, 15, 16, 13, 14,  5, 12,  6, 11,  9, 13, 10, 11,
+       9, 14,  9, 12, 11, 14, 11, 12, 16, 16, 14, 15, 15, 16, 13, 13,
+      10, 15,  9, 12, 12, 16, 11, 12, 12, 16, 10, 13, 13, 16, 11, 12,
+      16, 16, 13, 14, 15, 16, 13, 12,  6, 12,  8, 11,  8, 12, 10, 11,
+       9, 14, 10, 12, 10, 13, 11, 12, 15, 16, 14, 15, 14, 16, 13, 13,
+       8, 13,  9, 12, 10, 13, 10, 12, 10, 14,  9, 12, 11, 14, 10, 12,
+      15, 16, 13, 15, 14, 16, 13, 13, 11, 16, 10, 13, 13, 16, 11, 12,
+      12, 16, 11, 13, 13, 16, 11, 12, 16, 16, 13, 14, 15, 16, 12, 12,
+      10, 16, 12, 14, 10, 14, 11, 12, 12, 16, 13, 14, 11, 14, 12, 12,
+      16, 16, 15, 16, 14, 15, 13, 13, 11, 16, 12, 14, 11, 14, 11, 12,
+      12, 16, 12, 14, 11, 14, 11, 12, 16, 16, 14, 15, 13, 15, 13, 12,
+      14, 16, 13, 14, 13, 16, 12, 12, 14, 16, 13, 14, 13, 16, 12, 12,
+      16, 16, 14, 14, 14, 15, 12, 11,  2, 10,  6, 10,  7, 12,  9, 11,
+       8, 12,  9, 11, 10, 13, 10, 11, 15, 16, 14, 15, 14, 16, 13, 13,
+       5, 12,  6, 11,  9, 13, 10, 11,  9, 13,  9, 11, 10, 13, 10, 11,
+      15, 16, 13, 14, 14, 16, 13, 13,  9, 15,  8, 12, 12, 15, 11, 11,
+      11, 16, 10, 12, 13, 15, 11, 11, 15, 16, 13, 14, 15, 16, 12, 12,
+       6, 12,  8, 11,  8, 12,  9, 11,  9, 14,  9, 12, 10, 13, 10, 11,
+      15, 16, 14, 15, 14, 16, 13, 13,  7, 13,  8, 11,  9, 13, 10, 11,
+       9, 14,  9, 12, 10, 13, 10, 11, 14, 16, 13, 14, 13, 16, 12, 12,
+      11, 16, 10, 12, 12, 15, 11, 11, 11, 16, 10, 12, 12, 15, 11, 11,
+      15, 16, 12, 13, 14, 16, 12, 11,  9, 15, 11, 13,  9, 13, 11, 12,
+      11, 16, 12, 14, 10, 14, 11, 12, 16, 16, 14, 15, 13, 15, 12, 12,
+      11, 16, 11, 14, 10, 14, 11, 12, 11, 16, 12, 13, 11, 14, 11, 11,
+      15, 16, 14, 15, 13, 14, 12, 12, 13, 16, 12, 14, 13, 15, 11, 11,
+      13, 16, 12, 14, 13, 15, 11, 11, 16, 16, 13, 14, 13, 15, 11, 10,
+       5, 12,  7, 11,  8, 13, 10, 11,  9, 13,  9, 12, 10, 14, 11, 12,
+      16, 16, 14, 15, 14, 16, 13, 13,  7, 13,  7, 11,  9, 13, 10, 11,
+       9, 14,  9, 12, 11, 14, 11, 12, 16, 16, 14, 14, 14, 16, 13, 13,
+       9, 15,  8, 12, 12, 15, 11, 12, 11, 16, 10, 12, 13, 16, 11, 12,
+      16, 16, 13, 14, 15, 16, 12, 12,  7, 13,  8, 12,  9, 13, 10, 11,
+      10, 14, 10, 12, 10, 14, 11, 12, 16, 16, 14, 15, 14, 16, 13, 13,
+       8, 14,  9, 12, 10, 13, 10, 11,  9, 14,  9, 12, 10, 14, 10, 11,
+      15, 16, 13, 14, 14, 16, 12, 12, 11, 16, 10, 12, 12, 15, 11, 12,
+      11, 16, 10, 12, 12, 15, 11, 11, 15, 16, 12, 14, 14, 16, 12, 11,
+      10, 16, 11, 13,  9, 14, 11, 12, 12, 16, 12, 14, 11, 14, 11, 12,
+      16, 16, 14, 16, 14, 15, 13, 12, 11, 16, 11, 14, 10, 14, 11, 12,
+      11, 16, 12, 14, 11, 14, 11, 11, 15, 16, 14, 15, 13, 15, 12, 12,
+      13, 16, 12, 14, 13, 15, 11, 11, 13, 16, 12, 14, 12, 14, 11, 11,
+      15, 16, 12, 13, 13, 14, 11, 10,  6, 13,  8, 11,  9, 13, 10, 11,
+      10, 14, 10, 12, 10, 13, 10, 11, 15, 16, 13, 13, 13, 14, 12, 11,
+       7, 13,  8, 11,  9, 13,  9, 11, 10, 14,  9, 11, 10, 13, 10, 11,
+      15, 16, 13, 13, 13, 14, 11, 11,  9, 14,  8, 11, 10, 13,  9, 10,
+      11, 15,  9, 11, 11, 13,  9, 10, 15, 16, 12, 13, 13, 14, 10,  9,
+       7, 13,  8, 11,  9, 13,  9, 11, 10, 14, 10, 12, 10, 13, 10, 11,
+      15, 16, 13, 13, 13, 14, 11, 11,  8, 13,  8, 11,  9, 13,  9, 10,
+       9, 14,  9, 11, 10, 13,  9, 10, 14, 16, 12, 13, 13, 14, 11, 10,
+       9, 14,  8, 11, 10, 13,  9,  9, 10, 14,  8, 11, 10, 13,  9,  9,
+      14, 16, 11, 12, 12, 14, 10,  9,  9, 14,  9, 12,  8, 12,  9, 10,
+      11, 15, 10, 12, 10, 13,  9, 10, 15, 16, 13, 13, 12, 13, 11, 10,
+       9, 14,  9, 12,  9, 12,  9, 10, 10, 14, 10, 12,  9, 12,  9,  9,
+      14, 16, 12, 13, 11, 13, 10,  9, 10, 14,  9, 11, 10, 12,  8,  8,
+      10, 14,  9, 11, 10, 12,  8,  8, 12, 14,  9, 10, 10, 11,  8,  7,
+    ], [
+       0,  9,  6,  9,  6, 10,  8,  9,  7, 11,  8, 11,  9, 11,  9, 10,
+      14, 16, 13, 14, 13, 14, 12, 11,  5, 11,  7, 10,  8, 10,  8,  9,
+       8, 12,  8, 11,  9, 12,  9, 10, 14, 16, 12, 13, 13, 14, 11, 11,
+      10, 14,  9, 11, 11, 13, 10, 10, 11, 15,  9, 11, 12, 13, 10, 10,
+      15, 16, 12, 12, 13, 14, 11,  9,  6, 11,  7, 10,  7, 10,  8,  9,
+       8, 12,  9, 11,  9, 11,  9, 10, 14, 16, 13, 13, 13, 14, 11, 11,
+       7, 12,  8, 11,  8, 11,  9,  9,  9, 13,  9, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 12, 14, 11, 10, 11, 14, 10, 12, 11, 13, 10, 10,
+      12, 15, 10, 12, 12, 13, 10, 10, 15, 16, 12, 12, 13, 14, 10,  9,
+      10, 14, 11, 13,  9, 12, 10, 10, 11, 15, 12, 13, 10, 12, 10, 10,
+      14, 16, 13, 14, 12, 13, 11, 10, 11, 14, 11, 13, 10, 12, 10, 10,
+      12, 15, 11, 13, 10, 12, 10, 10, 15, 16, 13, 13, 12, 13, 11,  9,
+      13, 16, 12, 13, 12, 13, 10,  9, 14, 16, 12, 13, 12, 13, 10,  9,
+      16, 16, 12, 12, 13, 13, 10,  7,  4, 10,  6,  9,  7, 10,  8,  9,
+       8, 12,  9, 11,  9, 11,  9,  9, 14, 16, 13, 13, 13, 14, 11, 11,
+       6, 11,  7, 10,  8, 11,  8,  9,  9, 12,  9, 11,  9, 12,  9,  9,
+      14, 16, 12, 13, 13, 14, 11, 10, 10, 14,  9, 11, 11, 13,  9,  9,
+      11, 14,  9, 11, 11, 13, 10,  9, 14, 16, 11, 12, 13, 14, 10,  9,
+       6, 11,  8, 10,  7, 10,  8,  9,  9, 12,  9, 11,  9, 11,  9,  9,
+      14, 16, 13, 13, 12, 13, 11, 10,  8, 12,  8, 10,  8, 11,  9,  9,
+       9, 12,  9, 11,  9, 11,  9,  9, 14, 16, 12, 13, 12, 13, 11, 10,
+      11, 14, 10, 11, 11, 13,  9,  9, 11, 14, 10, 11, 11, 13,  9,  9,
+      14, 16, 11, 12, 13, 14, 10,  8, 10, 14, 11, 12,  9, 12, 10, 10,
+      11, 14, 11, 13, 10, 12, 10, 10, 14, 16, 13, 14, 12, 13, 11,  9,
+      11, 14, 11, 12, 10, 12, 10, 10, 11, 14, 11, 12, 10, 12, 10,  9,
+      14, 16, 13, 13, 11, 12, 10,  9, 13, 16, 12, 13, 12, 13, 10,  9,
+      13, 16, 11, 12, 11, 13, 10,  8, 15, 16, 12, 12, 12, 12,  9,  7,
+       8, 12,  8, 11,  9, 12,  9, 10, 10, 14, 10, 12, 11, 13, 10, 10,
+      16, 16, 14, 14, 14, 14, 12, 11,  8, 13,  8, 11,  9, 12, 10, 10,
+      11, 14, 10, 12, 11, 13, 10, 10, 16, 16, 13, 14, 14, 14, 12, 11,
+      11, 14,  9, 12, 11, 13, 10, 10, 12, 15, 10, 12, 12, 14, 10, 10,
+      15, 16, 12, 12, 14, 14, 11,  9,  9, 13,  9, 11,  9, 12, 10, 10,
+      11, 14, 10, 12, 10, 12, 10, 10, 15, 16, 14, 14, 13, 14, 12, 11,
+       9, 13,  9, 11, 10, 12, 10, 10, 10, 14, 10, 12, 10, 12, 10, 10,
+      15, 16, 13, 13, 13, 14, 11, 10, 11, 15, 10, 12, 11, 13, 10, 10,
+      11, 15, 10, 12, 12, 13, 10,  9, 15, 16, 11, 12, 13, 14, 10,  9,
+      11, 15, 11, 13, 10, 12, 10, 10, 12, 16, 12, 13, 11, 13, 10, 10,
+      16, 16, 14, 14, 12, 13, 11,  9, 11, 15, 11, 13, 10, 13, 10, 10,
+      12, 15, 12, 13, 10, 12, 10, 10, 14, 16, 13, 13, 12, 13, 10,  9,
+      13, 16, 12, 13, 12, 13, 10,  9, 13, 16, 11, 12, 11, 13, 10,  9,
+      14, 16, 11, 12, 12, 12,  9,  7, 10, 15, 10, 12, 11, 13, 10, 10,
+      12, 16, 12, 13, 12, 13, 11, 10, 16, 16, 14, 14, 14, 15, 12, 10,
+      10, 14, 10, 12, 10, 13, 10, 10, 12, 15, 11, 12, 11, 13, 10, 10,
+      16, 16, 14, 13, 14, 14, 11,  9, 11, 14, 10, 11, 11, 12,  9,  9,
+      12, 15, 10, 11, 11, 13,  9,  8, 16, 16, 12, 12, 13, 13, 10,  7,
+      10, 15, 10, 12, 10, 13, 10, 10, 12, 15, 11, 12, 11, 13, 10, 10,
+      16, 16, 14, 13, 14, 14, 11,  9, 10, 14, 10, 12, 10, 12, 10, 10,
+      12, 15, 11, 12, 11, 13, 10, 10, 16, 16, 13, 13, 13, 14, 11,  9,
+      11, 14, 10, 11, 10, 12,  9,  8, 11, 14,  9, 11, 11, 12,  9,  8,
+      14, 16, 10, 11, 12, 13,  9,  7, 11, 15, 11, 12, 10, 12, 10,  9,
+      13, 16, 11, 12, 11, 12, 10,  9, 16, 16, 13, 13, 12, 13, 10,  7,
+      11, 15, 10, 12, 10, 12,  9,  8, 12, 15, 11, 12, 10, 12,  9,  8,
+      14, 16, 12, 12, 11, 12,  9,  7, 11, 14, 10, 11, 10, 12,  8,  7,
+      11, 14,  9, 10, 10, 11,  8,  6, 12, 15,  9,  9,  9, 10,  7,  4,
+    ], [
+       0,  6,  3,  7,  3,  7,  6,  7,  5,  9,  6,  9,  7,  9,  8,  8,
+      16, 16, 16, 16, 16, 16, 16, 11,  3,  8,  5,  8,  6,  8,  7,  7,
+       7, 11,  7, 10,  8, 10,  8,  9, 16, 16, 16, 16, 16, 16, 14, 10,
+       8, 16,  7, 11, 10, 16,  9,  9, 11, 16,  9, 14, 16, 16, 10,  9,
+      16, 16, 16, 16, 16, 16, 16, 10,  3,  8,  5,  8,  5,  8,  7,  7,
+       7, 11,  8, 10,  8, 10,  8,  9, 16, 16, 16, 16, 16, 16, 16, 11,
+       6, 10,  7,  9,  7, 10,  8,  8,  8, 11,  8, 10,  8, 11,  8,  8,
+      16, 16, 16, 16, 16, 16, 11, 10, 10, 16,  9, 13, 11, 16, 10,  9,
+      11, 16,  9, 11, 16, 16, 10,  9, 16, 16, 11, 16, 16, 16, 11,  9,
+       9, 16, 10, 11,  8, 11,  9,  9, 11, 16, 12, 16, 10, 16, 10, 10,
+      16, 16, 16, 16, 16, 16, 16, 10, 10, 16, 11, 16, 10, 16, 10, 10,
+      11, 16, 11, 16, 10, 16, 10,  9, 16, 16, 16, 16, 16, 16, 11,  9,
+      16, 16, 16, 16, 16, 16, 11,  9, 16, 16, 16, 16, 16, 16, 11,  9,
+      16, 16, 11, 16, 16, 16,  9,  7, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       2,  8,  5,  9,  6,  9,  8,  8,  8, 12,  9, 11,  9, 11, 10, 10,
+      16, 16, 14, 16, 14, 16, 14, 12,  5, 10,  6,  9,  8, 10,  8,  9,
+       9, 12,  9, 11, 10, 12, 10, 10, 16, 16, 14, 15, 15, 16, 13, 12,
+      10, 13,  9, 12, 11, 12, 10, 10, 12, 15, 11, 12, 12, 13, 11, 10,
+      16, 16, 15, 14, 15, 16, 13, 12,  6, 10,  8, 10,  7, 10,  8,  9,
+       9, 13, 10, 11, 10, 12, 10, 10, 16, 16, 14, 16, 14, 16, 13, 12,
+       7, 11,  8, 11,  9, 11,  9,  9, 10, 13, 10, 11, 10, 12, 10,  9,
+      16, 16, 14, 14, 14, 15, 12, 11, 11, 14, 11, 12, 11, 13, 10, 10,
+      12, 15, 11, 13, 12, 13, 11, 10, 16, 16, 14, 16, 15, 15, 13, 11,
+      10, 13, 11, 12, 10, 12, 10, 10, 12, 15, 12, 13, 11, 13, 11, 11,
+      16, 16, 15, 16, 14, 15, 13, 11, 11, 14, 11, 13, 11, 12, 11, 10,
+      12, 16, 12, 13, 12, 13, 11, 10, 16, 16, 15, 16, 13, 15, 12, 11,
+      13, 15, 12, 13, 13, 14, 11, 11, 14, 16, 13, 13, 13, 14, 11, 11,
+      16, 16, 15, 14, 15, 15, 12, 10,  3,  8,  6,  9,  7,  9,  8,  8,
+       8, 12,  9, 11,  9, 11,  9,  9, 16, 16, 15, 15, 15, 16, 13, 12,
+       6, 10,  7,  9,  8, 10,  8,  8,  9, 12,  9, 11, 10, 12, 10,  9,
+      16, 16, 14, 14, 14, 15, 13, 11, 10, 13,  9, 11, 11, 12, 10, 10,
+      12, 14, 11, 12, 12, 13, 11, 10, 16, 16, 14, 14, 15, 15, 13, 11,
+       6, 10,  8, 10,  7, 10,  8,  9, 10, 12, 10, 11, 10, 11, 10,  9,
+      16, 16, 14, 15, 14, 15, 13, 11,  8, 11,  8, 10,  9, 11,  9,  9,
+       9, 13,  9, 11, 10, 11,  9,  9, 16, 16, 13, 14, 14, 14, 12, 10,
+      11, 14, 10, 12, 11, 12, 10, 10, 12, 14, 11, 12, 12, 13, 10, 10,
+      16, 16, 13, 14, 15, 15, 12, 10, 10, 13, 11, 12, 10, 12, 10, 10,
+      12, 14, 12, 13, 11, 13, 11, 10, 16, 16, 15, 14, 14, 14, 12, 11,
+      11, 14, 11, 12, 10, 12, 10, 10, 12, 15, 12, 12, 11, 13, 10, 10,
+      16, 16, 14, 15, 13, 14, 12, 10, 13, 15, 12, 13, 12, 13, 11, 10,
+      13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 15, 11,  9,
+       6, 10,  8, 10,  8, 11,  9, 10, 11, 13, 11, 12, 11, 13, 11, 10,
+      16, 16, 16, 16, 16, 16, 13, 12,  8, 11,  9, 11,  9, 11, 10, 10,
+      11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 15, 15, 16, 16, 13, 12,
+      11, 14, 10, 12, 12, 13, 11, 10, 13, 16, 12, 13, 13, 14, 11, 11,
+      16, 16, 15, 16, 16, 16, 13, 12,  8, 12,  9, 11,  9, 11, 10, 10,
+      11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 16, 16, 16, 16, 13, 12,
+       9, 12, 10, 11, 10, 12, 10, 10, 11, 14, 11, 12, 11, 13, 10, 10,
+      16, 16, 15, 14, 15, 15, 13, 11, 12, 14, 11, 13, 12, 13, 11, 10,
+      12, 15, 11, 12, 13, 13, 11, 10, 16, 16, 14, 15, 16, 15, 13, 11,
+      11, 15, 12, 13, 11, 13, 11, 10, 13, 16, 13, 14, 12, 14, 11, 11,
+      16, 16, 16, 16, 15, 15, 13, 12, 12, 14, 12, 13, 11, 13, 11, 10,
+      13, 15, 12, 13, 11, 13, 11, 10, 16, 16, 15, 15, 13, 15, 13, 11,
+      13, 16, 13, 13, 13, 13, 12, 11, 13, 16, 13, 13, 13, 13, 11, 10,
+      16, 16, 13, 15, 14, 14, 12,  9,  9, 13, 10, 12, 11, 13, 11, 11,
+      13, 16, 13, 14, 13, 14, 12, 11, 16, 16, 16, 16, 16, 16, 14, 12,
+      10, 14, 11, 13, 11, 13, 11, 10, 13, 16, 13, 13, 13, 14, 12, 11,
+      16, 16, 16, 16, 16, 16, 14, 12, 11, 15, 11, 13, 12, 13, 11, 10,
+      14, 16, 12, 13, 13, 14, 12, 10, 16, 16, 15, 16, 16, 16, 13, 11,
+      10, 14, 11, 12, 11, 13, 11, 10, 13, 16, 12, 13, 12, 14, 12, 11,
+      16, 16, 16, 16, 16, 16, 14, 12, 11, 14, 11, 12, 11, 13, 11, 10,
+      13, 15, 12, 13, 12, 13, 11, 10, 16, 16, 15, 15, 16, 16, 13, 11,
+      12, 15, 12, 13, 12, 13, 11, 10, 13, 16, 12, 13, 13, 13, 11, 10,
+      16, 16, 14, 14, 16, 15, 13, 10, 12, 15, 12, 13, 12, 13, 11, 10,
+      14, 16, 13, 14, 13, 14, 12, 11, 16, 16, 16, 16, 15, 16, 13, 11,
+      12, 16, 12, 13, 12, 13, 11, 10, 13, 16, 13, 13, 12, 14, 11, 10,
+      16, 16, 15, 16, 14, 15, 13, 10, 12, 15, 12, 14, 12, 13, 11, 10,
+      13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 14, 11,  8,
+    ],
+  ], [
+    [
+       0, 11,  5, 11,  7, 13, 10, 12,  7, 13,  9, 13, 10, 14, 12, 13,
+      16, 16, 15, 16, 16, 16, 15, 15,  4, 13,  6, 12, 10, 14, 11, 12,
+       8, 14,  9, 13, 11, 15, 12, 13, 16, 16, 15, 16, 15, 16, 15, 14,
+       9, 16,  9, 13, 13, 16, 12, 13, 12, 16, 10, 14, 14, 16, 13, 13,
+      16, 16, 14, 16, 16, 16, 14, 14,  5, 13,  8, 13,  8, 13, 11, 12,
+       9, 14, 10, 13, 10, 14, 12, 13, 16, 16, 15, 16, 15, 16, 14, 15,
+       7, 14,  9, 13, 10, 14, 11, 13,  9, 15, 10, 13, 11, 14, 12, 13,
+      16, 16, 14, 16, 15, 16, 14, 14, 11, 16, 11, 14, 13, 16, 12, 13,
+      12, 16, 11, 14, 14, 16, 12, 13, 16, 16, 14, 15, 16, 16, 14, 13,
+      10, 16, 12, 15, 10, 15, 12, 14, 12, 16, 13, 16, 11, 15, 13, 14,
+      16, 16, 16, 16, 14, 16, 14, 14, 11, 16, 12, 15, 11, 16, 12, 13,
+      12, 16, 13, 15, 12, 16, 12, 13, 16, 16, 16, 16, 14, 16, 14, 14,
+      14, 16, 13, 15, 14, 16, 13, 13, 14, 16, 14, 15, 14, 16, 13, 13,
+      16, 16, 15, 16, 15, 16, 13, 13,  2, 12,  6, 11,  7, 13, 10, 12,
+       7, 13,  9, 12, 10, 14, 11, 12, 16, 16, 15, 16, 15, 16, 14, 15,
+       5, 13,  6, 12,  9, 13, 10, 12,  8, 14,  9, 13, 11, 14, 11, 13,
+      16, 16, 14, 16, 15, 16, 14, 14,  9, 16,  8, 13, 12, 16, 11, 13,
+      11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 15, 16, 16, 13, 13,
+       5, 13,  8, 12,  7, 13, 10, 12,  8, 14, 10, 13, 10, 14, 11, 13,
+      16, 16, 14, 16, 15, 16, 14, 14,  7, 14,  8, 12,  9, 14, 11, 12,
+       8, 14,  9, 13, 10, 14, 11, 12, 15, 16, 14, 15, 14, 16, 13, 14,
+      11, 16, 10, 13, 13, 16, 12, 13, 11, 16, 10, 13, 13, 16, 12, 13,
+      16, 16, 13, 15, 15, 16, 13, 13,  9, 16, 12, 15,  9, 14, 11, 13,
+      11, 16, 13, 15, 11, 14, 12, 13, 16, 16, 15, 16, 14, 16, 14, 14,
+      11, 16, 12, 14, 11, 15, 12, 13, 11, 16, 12, 14, 11, 15, 12, 13,
+      16, 16, 15, 16, 14, 16, 13, 13, 13, 16, 13, 15, 13, 16, 12, 13,
+      14, 16, 13, 15, 13, 16, 12, 12, 16, 16, 14, 15, 14, 16, 12, 12,
+       4, 13,  7, 12,  8, 14, 11, 12,  9, 14, 10, 13, 11, 14, 12, 13,
+      16, 16, 15, 16, 16, 16, 15, 15,  6, 14,  7, 12, 10, 14, 11, 12,
+       9, 15, 10, 13, 11, 15, 12, 13, 16, 16, 15, 16, 16, 16, 14, 14,
+       9, 16,  8, 13, 12, 16, 11, 13, 12, 16, 10, 14, 13, 16, 12, 13,
+      16, 16, 14, 16, 16, 16, 14, 14,  6, 14,  8, 13,  8, 14, 11, 13,
+       9, 15, 10, 13, 11, 14, 12, 13, 16, 16, 15, 16, 16, 16, 14, 14,
+       7, 15,  9, 13, 10, 14, 11, 13,  9, 15, 10, 13, 11, 14, 11, 13,
+      16, 16, 14, 16, 15, 16, 14, 14, 10, 16, 10, 13, 12, 16, 12, 13,
+      11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 14, 15, 16, 13, 13,
+       9, 16, 12, 14,  9, 14, 11, 13, 12, 16, 12, 15, 11, 15, 12, 13,
+      16, 16, 16, 16, 15, 16, 14, 14, 10, 16, 12, 15, 11, 15, 12, 13,
+      11, 16, 12, 14, 11, 15, 12, 13, 16, 16, 14, 16, 13, 16, 13, 13,
+      13, 16, 13, 15, 13, 16, 12, 13, 13, 16, 12, 14, 13, 16, 12, 12,
+      15, 16, 13, 14, 13, 16, 12, 12,  6, 14,  8, 13,  9, 14, 10, 12,
+      10, 15, 10, 12, 11, 14, 11, 12, 16, 16, 14, 14, 14, 16, 13, 13,
+       7, 15,  8, 13,  9, 14, 10, 12, 10, 15, 10, 13, 11, 14, 11, 12,
+      16, 16, 14, 14, 14, 16, 13, 12,  9, 16,  8, 12, 11, 14, 10, 11,
+      11, 16, 10, 13, 11, 14, 10, 11, 16, 16, 13, 14, 14, 16, 12, 11,
+       7, 14,  9, 13,  9, 14, 10, 12, 10, 16, 10, 13, 11, 14, 11, 12,
+      16, 16, 14, 14, 14, 15, 13, 12,  7, 14,  9, 13,  9, 14, 10, 12,
+       9, 14, 10, 12, 10, 14, 11, 12, 15, 16, 13, 14, 14, 15, 12, 12,
+       9, 15,  9, 12, 11, 14, 10, 11, 10, 15,  9, 12, 11, 14, 10, 11,
+      14, 16, 11, 13, 13, 15, 11, 11,  9, 16, 10, 13,  9, 14, 10, 11,
+      11, 16, 11, 13, 10, 14, 10, 11, 16, 16, 14, 15, 13, 15, 12, 12,
+       9, 16, 10, 13,  9, 13, 10, 11, 10, 15, 10, 13, 10, 13, 10, 11,
+      14, 16, 13, 14, 12, 14, 11, 11, 11, 16, 10, 13, 11, 13,  9, 10,
+      11, 14, 10, 12, 10, 13,  9,  9, 13, 15, 10, 11, 11, 12,  9,  8,
+    ], [
+       0, 10,  5, 10,  6, 11,  8, 10,  7, 12,  8, 11,  9, 12,  9, 10,
+      14, 16, 13, 13, 13, 14, 12, 11,  5, 12,  6, 10,  8, 12,  9, 10,
+       8, 13,  8, 11,  9, 12,  9, 10, 14, 16, 12, 13, 13, 14, 11, 11,
+       9, 15,  8, 12, 11, 14, 10, 10, 11, 16,  9, 12, 12, 14, 10, 10,
+      14, 16, 11, 12, 13, 14, 11, 10,  5, 12,  8, 11,  7, 11,  9, 10,
+       8, 13,  9, 11,  9, 12,  9, 10, 14, 16, 12, 13, 13, 14, 11, 11,
+       7, 13,  8, 11,  9, 12,  9, 10,  9, 13,  9, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 12, 13, 11, 10, 11, 15, 10, 12, 12, 14, 10, 10,
+      12, 16, 10, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 10,  9,
+      10, 15, 11, 13,  9, 13, 10, 10, 11, 15, 12, 13, 10, 12, 10, 10,
+      14, 16, 13, 14, 12, 13, 11, 10, 11, 16, 11, 13, 10, 13, 10, 10,
+      11, 16, 11, 13, 10, 13, 10, 10, 14, 16, 13, 14, 12, 13, 11,  9,
+      13, 16, 12, 13, 12, 14, 11, 10, 14, 16, 12, 13, 12, 14, 10,  9,
+      16, 16, 12, 13, 13, 13, 10,  8,  3, 11,  6, 10,  7, 11,  9, 10,
+       8, 12,  8, 11,  9, 12,  9, 10, 14, 16, 13, 13, 13, 14, 11, 11,
+       5, 12,  6, 10,  8, 12,  9, 10,  8, 13,  8, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 13, 14, 11, 10,  9, 14,  8, 11, 11, 14, 10, 10,
+      11, 15,  9, 11, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11,  9,
+       6, 12,  8, 11,  7, 11,  9, 10,  8, 13,  9, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 13, 13, 11, 10,  7, 13,  8, 11,  8, 12,  9, 10,
+       9, 13,  9, 11,  9, 12,  9,  9, 14, 16, 12, 13, 12, 13, 11, 10,
+      10, 15,  9, 12, 11, 14, 10, 10, 11, 15,  9, 11, 11, 13, 10,  9,
+      14, 16, 11, 12, 13, 14, 10,  9,  9, 15, 11, 13,  9, 12, 10, 10,
+      11, 15, 11, 13,  9, 12, 10, 10, 14, 16, 13, 14, 12, 13, 11, 10,
+      10, 15, 11, 13, 10, 13, 10, 10, 11, 15, 11, 13, 10, 12, 10, 10,
+      14, 16, 12, 13, 11, 12, 10,  9, 13, 16, 12, 13, 12, 14, 10,  9,
+      13, 16, 11, 12, 12, 13, 10,  9, 14, 16, 11, 12, 12, 13,  9,  8,
+       7, 13,  8, 12,  9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 11,
+      16, 16, 13, 14, 14, 14, 12, 11,  8, 14,  8, 12,  9, 13, 10, 10,
+      10, 14, 10, 12, 11, 13, 10, 10, 16, 16, 13, 13, 14, 14, 12, 11,
+      10, 15,  9, 12, 11, 14, 10, 10, 12, 16, 10, 12, 12, 14, 10, 10,
+      16, 16, 12, 13, 14, 15, 11, 10,  8, 14,  9, 12,  9, 13, 10, 11,
+      10, 15, 10, 12, 10, 13, 10, 11, 16, 16, 13, 14, 14, 14, 12, 11,
+       8, 14,  9, 12,  9, 13, 10, 10, 10, 14, 10, 12, 10, 13, 10, 10,
+      15, 16, 13, 13, 13, 14, 11, 10, 10, 15, 10, 12, 12, 14, 10, 10,
+      11, 16,  9, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 10,  9,
+      11, 16, 11, 13, 10, 13, 10, 10, 12, 16, 12, 13, 10, 13, 11, 10,
+      15, 16, 14, 14, 12, 13, 11, 10, 11, 16, 11, 13, 10, 13, 10, 10,
+      11, 16, 12, 13, 10, 12, 10, 10, 14, 16, 13, 14, 11, 13, 11,  9,
+      13, 16, 12, 13, 12, 14, 10, 10, 12, 16, 11, 12, 12, 13, 10,  9,
+      14, 16, 11, 12, 11, 12,  9,  8, 10, 16, 10, 13, 11, 14, 11, 11,
+      12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 13, 14, 14, 12, 10,
+      10, 15, 10, 13, 10, 13, 10, 11, 12, 16, 11, 13, 11, 13, 11, 10,
+      16, 16, 14, 13, 14, 14, 12, 10, 11, 15,  9, 12, 11, 13, 10,  9,
+      12, 16, 10, 12, 12, 13, 10,  9, 16, 16, 12, 12, 13, 14, 10,  8,
+      10, 16, 10, 13, 10, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 10,
+      16, 16, 14, 13, 14, 14, 12, 10,  9, 15,  9, 12, 10, 13, 10, 10,
+      11, 16, 10, 12, 11, 13, 10, 10, 16, 16, 13, 13, 13, 14, 11,  9,
+      10, 15,  9, 11, 11, 13,  9,  9, 11, 15,  9, 11, 11, 13,  9,  8,
+      14, 16, 10, 11, 13, 13, 10,  8, 11, 16, 11, 13, 10, 13, 10,  9,
+      13, 16, 11, 13, 11, 13, 10,  9, 16, 16, 13, 13, 13, 13, 10,  8,
+      11, 16, 10, 12, 10, 13, 10,  9, 11, 16, 11, 12, 10, 12,  9,  9,
+      15, 16, 12, 13, 11, 12, 10,  8, 11, 16, 10, 12, 11, 12,  9,  8,
+      11, 15,  9, 11, 10, 12,  9,  7, 13, 15,  9,  9, 10, 10,  7,  5,
+    ], [
+       0,  7,  3,  8,  4,  9,  7,  8,  5, 10,  7, 10,  8, 11,  8,  9,
+      16, 16, 16, 16, 16, 16, 11, 10,  2, 10,  4,  9,  7, 10,  7,  8,
+       7, 16,  7, 10,  9, 16,  8,  9, 16, 16, 16, 16, 16, 16, 11, 10,
+       8, 16,  7, 10, 10, 16,  9,  8, 10, 16,  9, 11, 16, 16,  9,  9,
+      16, 16, 16, 16, 16, 16, 11,  9,  3, 10,  6,  9,  6, 11,  8,  8,
+       7, 16,  8, 10,  9, 16,  9,  9, 16, 16, 16, 16, 16, 16, 11, 10,
+       5, 16,  7, 10,  8, 11,  8,  8,  8, 16,  8, 10,  9, 16,  8,  8,
+      16, 16, 11, 16, 16, 16, 10,  9,  9, 16,  9, 11, 11, 16,  9,  9,
+      11, 16,  9, 11, 11, 16,  9,  8, 16, 16, 10, 16, 16, 16, 10,  9,
+       8, 16, 10, 16,  8, 16, 10,  9, 12, 16, 11, 16, 10, 16, 10,  9,
+      16, 16, 16, 16, 16, 16, 12, 10, 10, 16, 11, 16, 10, 16, 10,  9,
+      11, 16, 11, 16, 10, 16, 10,  9, 16, 16, 16, 16, 16, 16, 11,  9,
+      16, 16, 16, 16, 16, 16, 10,  9, 16, 16, 11, 16, 16, 16, 10,  9,
+      16, 16, 10, 11, 11, 16,  9,  7, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       2,  9,  6,  9,  6, 10,  8,  9,  8, 12,  9, 11,  9, 12, 10, 10,
+      16, 16, 14, 14, 15, 15, 13, 12,  5, 11,  7, 10,  8, 11,  9,  9,
+       9, 13,  9, 11, 10, 12, 10, 10, 15, 16, 14, 14, 14, 16, 12, 11,
+      10, 14,  9, 11, 11, 13, 10, 10, 12, 15, 10, 12, 12, 13, 11, 10,
+      16, 16, 14, 15, 14, 15, 12, 11,  5, 11,  8, 10,  7, 11,  9,  9,
+       9, 13,  9, 12,  9, 12, 10, 10, 15, 16, 13, 14, 13, 16, 12, 11,
+       7, 12,  8, 11,  9, 11,  9, 10,  9, 13,  9, 11, 10, 12,  9,  9,
+      16, 16, 13, 14, 13, 14, 11, 11, 10, 14, 10, 12, 11, 13, 10, 10,
+      11, 16, 11, 12, 12, 13, 10, 10, 16, 16, 13, 14, 13, 14, 12, 11,
+      10, 14, 11, 13, 10, 13, 10, 11, 12, 16, 12, 13, 10, 12, 11, 11,
+      16, 16, 14, 15, 13, 14, 12, 11, 11, 15, 11, 13, 11, 13, 10, 10,
+      12, 15, 12, 13, 11, 13, 11, 10, 15, 16, 14, 15, 13, 15, 12, 11,
+      12, 16, 12, 13, 12, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 10,
+      16, 16, 13, 14, 13, 14, 11, 10,  3, 10,  6,  9,  7, 10,  8,  9,
+       9, 12,  9, 11, 10, 12,  9, 10, 15, 16, 14, 14, 14, 14, 12, 11,
+       6, 11,  7, 10,  8, 10,  9,  9,  9, 13,  9, 11, 10, 12,  9,  9,
+      15, 16, 13, 14, 14, 15, 12, 11, 10, 14,  9, 11, 11, 12, 10, 10,
+      12, 14, 10, 12, 11, 13, 10, 10, 15, 16, 13, 14, 14, 16, 12, 11,
+       6, 11,  8, 10,  7, 11,  9,  9,  9, 13,  9, 11,  9, 12,  9,  9,
+      15, 16, 14, 14, 13, 14, 12, 11,  7, 11,  8, 11,  8, 11,  9,  9,
+       9, 12,  9, 11,  9, 12,  9,  9, 15, 16, 13, 13, 13, 14, 11, 10,
+      10, 13, 10, 12, 11, 13, 10, 10, 11, 15, 10, 12, 11, 13, 10, 10,
+      14, 16, 12, 13, 13, 14, 11, 10, 10, 14, 11, 12,  9, 12, 10, 10,
+      11, 15, 11, 13, 10, 13, 10, 10, 15, 16, 14, 14, 13, 14, 12, 11,
+      10, 14, 10, 12, 10, 12, 10, 10, 11, 15, 11, 12, 10, 12, 10, 10,
+      15, 16, 13, 14, 12, 14, 11, 10, 12, 16, 11, 13, 12, 14, 11, 10,
+      12, 16, 12, 13, 11, 13, 10, 10, 15, 16, 12, 14, 12, 14, 11,  9,
+       7, 12,  9, 11,  9, 12, 10, 10, 11, 14, 11, 12, 11, 13, 11, 11,
+      16, 16, 15, 16, 15, 16, 13, 12,  8, 12,  9, 11,  9, 12, 10, 10,
+      11, 14, 11, 12, 11, 13, 10, 10, 16, 16, 14, 15, 15, 16, 13, 12,
+      11, 14, 10, 12, 11, 13, 10, 10, 12, 16, 11, 13, 12, 14, 11, 10,
+      16, 16, 14, 15, 14, 16, 12, 11,  8, 13,  9, 11,  9, 12, 10, 10,
+      11, 14, 11, 12, 11, 13, 10, 10, 16, 16, 15, 15, 14, 15, 13, 12,
+       9, 13,  9, 12,  9, 12, 10, 10, 11, 14, 10, 12, 10, 12, 10, 10,
+      16, 16, 14, 15, 14, 14, 12, 11, 11, 15, 11, 12, 11, 13, 11, 10,
+      12, 16, 11, 12, 12, 13, 11, 10, 16, 16, 13, 15, 14, 15, 11, 11,
+      11, 16, 11, 13, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      16, 16, 14, 15, 14, 15, 13, 11, 11, 16, 11, 13, 11, 13, 11, 10,
+      12, 16, 12, 13, 10, 13, 11, 10, 16, 16, 14, 14, 12, 14, 12, 10,
+      12, 16, 12, 14, 12, 14, 11, 11, 13, 16, 12, 14, 12, 14, 11, 10,
+      15, 16, 12, 14, 12, 14, 11,  9,  9, 14, 11, 13, 11, 13, 11, 11,
+      13, 16, 12, 14, 13, 14, 12, 11, 16, 16, 16, 16, 16, 16, 14, 12,
+       9, 14, 10, 12, 10, 13, 11, 11, 12, 16, 12, 13, 13, 14, 11, 11,
+      16, 16, 16, 16, 16, 14, 13, 12, 10, 15, 11, 13, 11, 14, 11, 10,
+      13, 16, 12, 13, 12, 15, 11, 10, 16, 16, 14, 16, 15, 16, 13, 11,
+      10, 14, 10, 13, 11, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 11,
+      16, 16, 16, 16, 15, 16, 13, 12, 10, 14, 10, 12, 10, 13, 10, 11,
+      12, 15, 12, 13, 12, 13, 11, 10, 16, 16, 14, 14, 15, 15, 13, 11,
+      11, 16, 11, 13, 11, 14, 11, 10, 12, 16, 11, 13, 12, 14, 11, 10,
+      16, 16, 13, 14, 14, 15, 12, 10, 11, 16, 12, 13, 11, 14, 11, 10,
+      13, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 15, 15, 12, 11,
+      11, 16, 12, 13, 11, 14, 11, 10, 13, 16, 12, 13, 11, 14, 11, 10,
+      16, 16, 14, 15, 13, 14, 12, 10, 12, 16, 12, 14, 12, 14, 10, 10,
+      12, 16, 11, 13, 11, 14, 10, 10, 14, 16, 11, 13, 12, 13, 10,  8,
+    ],
+  ], [
+    [
+       0, 12,  6, 13,  7, 14, 11, 14,  8, 14, 10, 14, 11, 15, 13, 15,
+      16, 16, 16, 16, 16, 16, 16, 16,  5, 14,  7, 13, 10, 16, 12, 14,
+       9, 16, 10, 14, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16,  9, 14, 14, 16, 13, 16, 12, 16, 11, 16, 16, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  5, 14,  9, 14,  8, 14, 12, 14,
+       9, 16, 11, 14, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 14, 11, 16, 12, 14, 10, 16, 11, 15, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 14, 16,
+      13, 16, 12, 16, 15, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 13, 16, 11, 16, 14, 16, 13, 16, 14, 16, 13, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 14, 16, 13, 16, 14, 16,
+      13, 16, 14, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 12,  6, 12,  8, 14, 11, 13,
+       8, 14, 10, 13, 11, 14, 13, 14, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 14,  7, 13, 10, 14, 11, 14,  9, 16, 10, 14, 12, 16, 13, 15,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16,  9, 14, 13, 16, 13, 14,
+      12, 16, 11, 15, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 14,  9, 13,  8, 14, 12, 14,  9, 16, 11, 14, 11, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 15,  9, 14, 10, 16, 12, 14,
+       9, 16, 10, 14, 11, 16, 12, 14, 16, 16, 16, 16, 16, 16, 15, 16,
+      11, 16, 11, 15, 14, 16, 13, 15, 12, 16, 11, 15, 14, 16, 13, 14,
+      16, 16, 14, 16, 16, 16, 14, 16, 10, 16, 13, 16, 10, 16, 13, 16,
+      12, 16, 14, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 15, 16, 14, 16, 14, 16, 16, 16, 14, 16,
+      15, 16, 14, 16, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 14,
+       4, 14,  8, 13,  9, 16, 12, 14,  9, 16, 11, 14, 11, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 15,  8, 13, 10, 16, 12, 14,
+      10, 16, 11, 14, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16,  9, 14, 13, 16, 13, 15, 12, 16, 11, 16, 14, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16,  9, 14,  9, 16, 12, 14,
+      10, 16, 11, 15, 12, 16, 13, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 14, 11, 16, 12, 14, 10, 16, 11, 14, 12, 16, 13, 15,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 15, 14, 16, 13, 15,
+      12, 16, 11, 15, 14, 16, 13, 14, 16, 16, 14, 16, 16, 16, 14, 16,
+      10, 16, 13, 16, 10, 16, 13, 15, 13, 16, 14, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 12, 16, 13, 16,
+      12, 16, 13, 16, 11, 16, 13, 16, 16, 16, 16, 16, 15, 16, 15, 16,
+      14, 16, 14, 16, 15, 16, 14, 16, 14, 16, 14, 16, 14, 16, 14, 14,
+      16, 16, 14, 16, 15, 16, 14, 14,  6, 16,  9, 14, 10, 16, 12, 14,
+      10, 16, 11, 13, 12, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14,
+       7, 16,  9, 14, 10, 16, 12, 13, 11, 16, 11, 14, 12, 16, 12, 14,
+      16, 16, 16, 16, 16, 16, 14, 14,  9, 16,  9, 14, 12, 16, 11, 13,
+      12, 16, 11, 14, 12, 16, 12, 13, 16, 16, 14, 16, 16, 16, 13, 14,
+       7, 16, 10, 14, 10, 16, 12, 14, 11, 16, 11, 14, 11, 16, 12, 14,
+      16, 16, 16, 16, 16, 16, 14, 14,  8, 16, 10, 14, 10, 16, 11, 13,
+      10, 16, 11, 13, 11, 16, 12, 13, 16, 16, 14, 16, 16, 16, 14, 14,
+      10, 16,  9, 13, 12, 16, 11, 13, 11, 16, 10, 13, 12, 16, 11, 12,
+      16, 16, 13, 15, 15, 16, 13, 13,  9, 16, 11, 14,  9, 16, 11, 13,
+      12, 16, 12, 16, 12, 16, 12, 13, 16, 16, 16, 16, 15, 16, 14, 14,
+      10, 16, 11, 14, 10, 16, 11, 13, 11, 16, 12, 14, 10, 15, 11, 13,
+      16, 16, 15, 16, 13, 16, 13, 13, 12, 16, 11, 13, 12, 16, 11, 12,
+      12, 16, 11, 13, 11, 14, 11, 11, 13, 16, 12, 13, 12, 14, 11, 11,
+    ], [
+       0, 10,  5, 10,  6, 11,  8, 10,  7, 12,  8, 11,  8, 12,  9, 10,
+      14, 16, 13, 13, 13, 14, 12, 11,  4, 12,  6, 10,  8, 12,  9, 10,
+       8, 13,  8, 11,  9, 12,  9, 10, 14, 16, 12, 13, 13, 14, 11, 11,
+       9, 15,  8, 12, 12, 14, 10, 11, 11, 16,  9, 12, 12, 14, 10, 10,
+      14, 16, 11, 13, 13, 15, 11, 11,  4, 12,  8, 11,  6, 11,  9, 10,
+       8, 13,  9, 11,  8, 12,  9, 10, 14, 16, 12, 13, 13, 14, 11, 11,
+       7, 13,  8, 11,  9, 12,  9, 10,  8, 13,  9, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 12, 13, 11, 10, 11, 16, 10, 12, 12, 14, 10, 11,
+      11, 16, 10, 12, 12, 14, 10, 10, 15, 16, 11, 13, 13, 14, 11, 10,
+      10, 16, 11, 13,  9, 13, 10, 11, 11, 15, 12, 13, 10, 12, 10, 11,
+      15, 16, 13, 14, 12, 13, 11, 11, 11, 16, 11, 13, 10, 13, 10, 11,
+      12, 16, 11, 13, 10, 13, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10,
+      13, 16, 12, 13, 13, 14, 11, 11, 14, 16, 12, 13, 12, 14, 11, 10,
+      16, 16, 13, 13, 13, 14, 11,  9,  3, 11,  6, 10,  6, 11,  9, 10,
+       8, 12,  8, 11,  9, 12,  9, 10, 14, 16, 13, 13, 13, 13, 12, 11,
+       5, 12,  6, 10,  8, 12,  9, 10,  8, 13,  8, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 13, 14, 11, 11,  9, 15,  8, 11, 11, 14, 10, 10,
+      11, 15,  9, 11, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11, 10,
+       5, 12,  8, 11,  7, 11,  9, 10,  8, 13,  9, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 13, 13, 11, 11,  7, 13,  8, 11,  8, 12,  9, 10,
+       8, 13,  8, 11,  9, 12,  9,  9, 13, 16, 11, 13, 12, 13, 11, 10,
+      10, 15,  9, 12, 11, 14, 10, 10, 11, 15,  9, 11, 11, 13, 10, 10,
+      14, 16, 11, 12, 13, 14, 10, 10,  9, 16, 11, 13,  9, 12, 10, 10,
+      11, 16, 11, 13,  9, 12, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10,
+      11, 16, 11, 13, 10, 13, 10, 10, 11, 15, 11, 13,  9, 12, 10, 10,
+      14, 16, 12, 13, 11, 13, 10, 10, 13, 16, 12, 13, 12, 14, 11, 10,
+      13, 16, 11, 13, 12, 13, 10, 10, 14, 16, 11, 12, 12, 13, 10,  9,
+       7, 14,  8, 12,  9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 11,
+      16, 16, 14, 14, 14, 14, 12, 12,  7, 14,  8, 12,  9, 13, 10, 11,
+      10, 14, 10, 12, 11, 13, 10, 11, 16, 16, 13, 13, 14, 14, 12, 11,
+      10, 15,  9, 12, 12, 14, 10, 10, 12, 16,  9, 12, 12, 14, 10, 10,
+      16, 16, 12, 13, 14, 15, 12, 11,  8, 14,  9, 12,  9, 13, 10, 11,
+      10, 15, 10, 12, 10, 13, 10, 11, 16, 16, 14, 14, 14, 14, 12, 11,
+       8, 14,  9, 12,  9, 13, 10, 11, 10, 14, 10, 12, 10, 13, 10, 10,
+      15, 16, 13, 13, 13, 14, 12, 11, 10, 15, 10, 12, 12, 14, 10, 10,
+      11, 16,  9, 12, 12, 14, 10, 10, 14, 16, 11, 12, 13, 14, 11, 10,
+      11, 16, 11, 14,  9, 13, 10, 11, 12, 16, 12, 14, 10, 13, 11, 11,
+      16, 16, 14, 15, 13, 14, 12, 11, 11, 16, 12, 14, 10, 13, 11, 11,
+      11, 16, 11, 13, 10, 13, 10, 10, 15, 16, 13, 14, 12, 13, 11, 10,
+      13, 16, 12, 14, 13, 14, 11, 10, 12, 16, 11, 13, 12, 13, 10, 10,
+      14, 16, 11, 12, 11, 13, 10,  9, 10, 16, 10, 13, 11, 14, 11, 11,
+      12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 13, 14, 15, 12, 11,
+      10, 16, 10, 13, 10, 14, 11, 11, 12, 16, 11, 13, 11, 14, 11, 11,
+      16, 16, 14, 13, 14, 14, 12, 11, 11, 15,  9, 12, 11, 14, 10, 10,
+      13, 16, 10, 12, 12, 14, 10, 10, 16, 16, 13, 13, 14, 14, 11, 10,
+      10, 16, 10, 13, 11, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11,
+      16, 16, 14, 14, 14, 14, 12, 11,  9, 16, 10, 13, 10, 14, 11, 11,
+      11, 15, 11, 12, 11, 13, 11, 11, 16, 16, 13, 13, 14, 14, 12, 10,
+      10, 15,  9, 12, 11, 14, 10, 10, 11, 16,  9, 11, 11, 13, 10,  9,
+      15, 16, 11, 12, 13, 14, 10,  9, 11, 16, 11, 13, 10, 13, 10, 10,
+      13, 16, 12, 13, 11, 13, 10, 10, 16, 16, 14, 14, 13, 13, 11, 10,
+      11, 16, 11, 13, 10, 13, 10, 10, 12, 16, 11, 13, 10, 13, 10, 10,
+      15, 16, 13, 13, 12, 13, 11,  9, 11, 16, 11, 12, 11, 13, 10,  9,
+      11, 15, 10, 11, 11, 12,  9,  8, 13, 15, 10, 10, 10, 11,  8,  7,
+    ], [
+       0,  9,  3,  8,  5,  9,  7,  8,  5, 11,  6,  9,  8, 11,  8,  9,
+      16, 16, 16, 16, 16, 16, 11, 10,  2, 10,  4,  9,  7, 10,  7,  8,
+       7, 16,  7, 10,  9, 11,  8,  9, 16, 16, 11, 16, 16, 16, 11, 10,
+       7, 16,  7, 10, 10, 16,  8,  9, 10, 16,  8, 10, 11, 16,  9,  9,
+      16, 16, 16, 16, 16, 16, 11, 10,  3, 11,  6,  9,  6, 11,  8,  8,
+       7, 16,  8, 10,  8, 11,  8,  9, 16, 16, 15, 16, 16, 16, 11, 10,
+       5, 11,  7,  9,  8, 11,  8,  8,  7, 16,  7, 10,  8, 11,  8,  8,
+      16, 16, 11, 16, 16, 16, 10,  9,  9, 16,  8, 11, 11, 16,  9,  9,
+      10, 16,  8, 11, 11, 16,  9,  9, 16, 16, 10, 16, 16, 16, 10,  9,
+       8, 16, 10, 11,  8, 16,  9,  9, 11, 16, 11, 16, 10, 16, 10,  9,
+      16, 16, 16, 16, 16, 16, 11, 10,  9, 16, 10, 16, 10, 16,  9,  9,
+      10, 16, 10, 16,  9, 16,  9,  9, 16, 16, 16, 16, 15, 16, 10,  9,
+      16, 16, 11, 16, 16, 16, 10, 10, 13, 16, 11, 16, 11, 16, 10,  9,
+      16, 16, 10, 11, 11, 16,  9,  8, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       1, 10,  6, 10,  7, 11,  9, 10,  8, 12,  9, 12,  9, 12, 10, 10,
+      16, 16, 14, 16, 14, 15, 13, 12,  5, 12,  7, 10,  9, 11,  9, 10,
+       9, 13,  9, 12, 10, 13, 10, 10, 16, 16, 14, 15, 14, 14, 13, 12,
+      10, 15, 10, 12, 12, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11,
+      16, 16, 14, 16, 15, 16, 13, 12,  6, 12,  8, 11,  8, 11, 10, 10,
+       9, 13, 10, 12, 10, 12, 10, 10, 15, 16, 13, 15, 13, 14, 12, 12,
+       7, 13,  9, 11,  9, 12, 10, 10,  9, 14, 10, 12, 10, 13, 10, 10,
+      15, 16, 13, 15, 13, 14, 12, 11, 11, 15, 11, 13, 12, 14, 11, 11,
+      12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 11,
+      10, 16, 12, 14, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      16, 16, 15, 16, 14, 16, 13, 12, 11, 16, 12, 14, 11, 14, 11, 11,
+      12, 16, 12, 14, 11, 14, 11, 11, 16, 16, 14, 15, 13, 15, 12, 12,
+      13, 16, 13, 15, 13, 15, 12, 12, 13, 16, 12, 15, 12, 15, 11, 11,
+      16, 16, 13, 16, 13, 15, 12, 11,  4, 11,  7, 10,  7, 11,  9, 10,
+       9, 13,  9, 12, 10, 12, 10, 10, 15, 16, 14, 15, 14, 15, 13, 12,
+       6, 12,  7, 11,  9, 11,  9, 10,  9, 13,  9, 12, 10, 12, 10, 10,
+      15, 16, 14, 15, 14, 15, 12, 12, 10, 15,  9, 12, 12, 13, 11, 11,
+      12, 15, 11, 13, 12, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 12,
+       6, 12,  8, 11,  8, 11,  9, 10,  9, 14, 10, 12, 10, 12, 10, 10,
+      14, 16, 13, 14, 13, 14, 12, 12,  8, 13,  9, 11,  9, 12, 10, 10,
+       9, 13,  9, 12,  9, 12,  9, 10, 14, 16, 13, 14, 13, 14, 12, 11,
+      11, 15, 11, 13, 11, 14, 11, 11, 12, 16, 10, 13, 12, 13, 11, 10,
+      15, 16, 12, 15, 13, 16, 12, 11, 10, 15, 11, 13, 10, 13, 11, 11,
+      12, 16, 12, 14, 11, 13, 11, 11, 16, 16, 14, 15, 13, 16, 13, 12,
+      11, 16, 11, 14, 11, 13, 11, 11, 12, 16, 12, 14, 10, 13, 11, 11,
+      15, 16, 13, 16, 12, 14, 12, 11, 12, 16, 12, 14, 12, 15, 11, 11,
+      13, 16, 12, 14, 12, 14, 11, 11, 15, 16, 13, 15, 13, 15, 11, 10,
+       7, 13,  9, 12, 10, 13, 11, 11, 11, 15, 12, 13, 12, 13, 11, 11,
+      16, 16, 15, 16, 16, 16, 14, 13,  8, 13,  9, 12, 10, 13, 11, 11,
+      12, 15, 11, 13, 12, 13, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12,
+      11, 16, 11, 13, 12, 14, 11, 11, 13, 16, 12, 14, 13, 15, 12, 11,
+      16, 16, 14, 16, 15, 16, 13, 12,  9, 15, 10, 13, 10, 13, 11, 11,
+      12, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 16, 16, 16, 13, 12,
+       9, 14, 10, 13, 10, 13, 11, 11, 11, 14, 11, 13, 11, 13, 11, 11,
+      16, 16, 14, 16, 14, 16, 12, 12, 11, 16, 11, 14, 12, 14, 12, 11,
+      12, 16, 11, 13, 13, 14, 11, 11, 16, 16, 13, 15, 14, 16, 12, 11,
+      12, 16, 12, 14, 11, 14, 11, 11, 13, 16, 13, 14, 12, 15, 12, 11,
+      16, 16, 16, 16, 14, 16, 13, 12, 12, 16, 12, 14, 11, 14, 12, 11,
+      12, 16, 12, 15, 11, 14, 11, 11, 16, 16, 14, 16, 13, 15, 12, 12,
+      13, 16, 13, 16, 13, 16, 12, 12, 13, 16, 12, 15, 12, 16, 11, 11,
+      14, 16, 12, 15, 12, 15, 11, 10,  9, 16, 11, 14, 12, 14, 12, 12,
+      13, 16, 13, 15, 14, 16, 12, 12, 16, 16, 16, 16, 16, 16, 14, 13,
+      10, 16, 11, 14, 12, 14, 12, 12, 13, 16, 13, 14, 13, 16, 12, 12,
+      16, 16, 15, 16, 16, 16, 13, 12, 11, 16, 11, 14, 12, 15, 12, 11,
+      13, 16, 12, 14, 13, 16, 12, 11, 16, 16, 14, 16, 16, 16, 13, 12,
+      11, 16, 11, 14, 12, 14, 12, 12, 13, 16, 12, 15, 13, 16, 12, 12,
+      16, 16, 16, 16, 16, 16, 14, 13, 10, 16, 11, 14, 11, 15, 11, 11,
+      13, 16, 12, 14, 12, 14, 12, 11, 16, 16, 14, 16, 16, 16, 13, 12,
+      11, 16, 11, 15, 12, 15, 12, 11, 13, 16, 11, 14, 13, 15, 12, 11,
+      16, 16, 13, 16, 14, 16, 12, 11, 12, 16, 12, 15, 11, 15, 12, 11,
+      14, 16, 13, 15, 12, 16, 12, 11, 16, 16, 15, 16, 14, 16, 13, 12,
+      11, 16, 12, 15, 11, 15, 11, 11, 13, 16, 13, 16, 11, 15, 11, 11,
+      16, 16, 14, 16, 13, 15, 12, 11, 12, 16, 12, 15, 12, 16, 11, 11,
+      12, 16, 11, 15, 12, 14, 11, 11, 13, 16, 12, 13, 11, 13, 10,  9,
+    ],
+  ], [
+    [
+       0, 13,  6, 13,  8, 14, 12, 16,  8, 16, 11, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 16,  7, 14, 11, 16, 13, 16,
+       9, 16, 11, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 10, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  5, 16, 10, 16,  8, 16, 13, 16,
+      10, 16, 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16, 11, 16, 13, 16, 10, 16, 12, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 16, 16, 16, 16,
+      14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 16, 16, 11, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16,
+      14, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 13,  7, 13,  8, 16, 12, 16,
+       8, 16, 10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       4, 16,  7, 14, 10, 16, 12, 16,  9, 16, 10, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 10, 16,  9, 16, 14, 16, 14, 16,
+      13, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16,  9, 16,  8, 16, 12, 16,  9, 16, 11, 16, 11, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 16, 10, 16, 11, 16, 13, 16,
+       9, 16, 11, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 12, 16, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 13, 16, 11, 16, 14, 16,
+      13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 14, 16, 13, 16, 14, 16, 13, 16, 14, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       4, 16,  8, 16,  9, 16, 13, 16, 10, 16, 11, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16,  8, 16, 11, 16, 13, 16,
+      10, 16, 11, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16,  9, 16, 13, 16, 13, 16, 13, 16, 12, 16, 16, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 10, 16, 10, 16, 13, 16,
+      10, 16, 12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16, 11, 16, 13, 16, 10, 16, 11, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 14, 16,
+      12, 16, 11, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 13, 16, 10, 16, 13, 16, 13, 16, 16, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 12, 16, 14, 16,
+      12, 16, 15, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 10, 16, 10, 16, 13, 16,
+      11, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16,  9, 16, 11, 16, 12, 16, 11, 16, 11, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16,  9, 16, 12, 16, 12, 16,
+      13, 16, 11, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16, 10, 16, 12, 16, 11, 16, 12, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 10, 16, 11, 16, 12, 16,
+      10, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 10, 14, 12, 16, 12, 16, 11, 16, 10, 14, 13, 16, 12, 14,
+      16, 16, 14, 16, 16, 16, 14, 16,  9, 16, 12, 16, 10, 16, 12, 16,
+      13, 16, 13, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 11, 16, 12, 16, 11, 16, 12, 16, 11, 16, 12, 15,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 12, 16, 13, 16, 12, 13,
+      12, 16, 12, 16, 12, 16, 12, 13, 16, 16, 13, 14, 13, 16, 13, 13,
+    ], [
+       0, 10,  5, 10,  5, 10,  8, 10,  6, 11,  8, 11,  8, 11,  9, 10,
+      14, 16, 13, 14, 13, 14, 12, 12,  4, 12,  5, 10,  8, 12,  9, 10,
+       7, 12,  8, 11,  9, 12,  9, 10, 14, 16, 12, 13, 13, 14, 12, 12,
+       9, 16,  8, 12, 12, 14, 10, 11, 11, 16,  9, 12, 12, 14, 11, 11,
+      14, 16, 12, 13, 14, 15, 12, 12,  4, 12,  7, 11,  6, 11,  9, 10,
+       8, 12,  9, 11,  8, 11,  9, 10, 14, 16, 12, 14, 13, 14, 12, 12,
+       7, 13,  8, 11,  8, 12,  9, 10,  8, 13,  8, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 12, 13, 11, 11, 11, 16, 10, 12, 12, 14, 11, 11,
+      12, 16, 10, 12, 12, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 11,
+      10, 16, 11, 14,  9, 13, 10, 11, 11, 16, 12, 14, 10, 13, 11, 11,
+      15, 16, 13, 14, 13, 14, 12, 12, 11, 16, 12, 14, 10, 13, 11, 11,
+      12, 16, 12, 14, 11, 13, 11, 11, 15, 16, 13, 14, 13, 14, 12, 11,
+      14, 16, 13, 14, 13, 15, 12, 12, 14, 16, 12, 14, 13, 15, 11, 11,
+      16, 16, 13, 14, 14, 15, 12, 11,  3, 11,  5, 10,  6, 11,  9, 10,
+       7, 12,  8, 11,  9, 11,  9, 10, 14, 16, 13, 13, 13, 14, 12, 12,
+       5, 12,  6, 10,  8, 12,  9, 10,  8, 13,  8, 11,  9, 12,  9, 10,
+      14, 16, 12, 13, 13, 14, 12, 12,  9, 16,  8, 11, 11, 14, 10, 11,
+      11, 16,  9, 12, 12, 14, 10, 11, 15, 16, 12, 13, 14, 15, 12, 11,
+       5, 12,  7, 11,  6, 11,  9, 10,  8, 13,  9, 11,  8, 11,  9, 10,
+      14, 16, 12, 14, 13, 13, 12, 12,  7, 13,  8, 11,  8, 12,  9, 10,
+       8, 12,  8, 11,  9, 12,  9, 10, 13, 16, 12, 13, 12, 13, 11, 11,
+      10, 16,  9, 12, 12, 14, 10, 11, 11, 15,  9, 12, 12, 14, 10, 11,
+      14, 16, 11, 13, 13, 14, 11, 11,  9, 16, 11, 14,  8, 13, 10, 11,
+      11, 16, 12, 13, 10, 13, 10, 11, 16, 16, 13, 15, 13, 14, 12, 12,
+      11, 16, 11, 14, 10, 13, 10, 11, 11, 16, 11, 13, 10, 13, 10, 11,
+      14, 16, 13, 14, 12, 13, 11, 11, 14, 16, 12, 14, 13, 15, 11, 11,
+      13, 16, 12, 13, 12, 14, 11, 11, 14, 16, 12, 13, 12, 13, 11, 10,
+       6, 14,  8, 12,  9, 13, 10, 11, 10, 14, 10, 12, 11, 13, 11, 12,
+      16, 16, 14, 14, 14, 14, 13, 12,  7, 14,  8, 12,  9, 13, 10, 11,
+      10, 14, 10, 12, 11, 13, 11, 11, 16, 16, 13, 14, 14, 15, 13, 12,
+      10, 16,  8, 12, 12, 14, 10, 11, 12, 16, 10, 12, 13, 15, 11, 11,
+      16, 16, 13, 14, 15, 16, 12, 12,  8, 15,  9, 13,  9, 13, 10, 11,
+      10, 15, 10, 13, 10, 13, 11, 11, 16, 16, 14, 14, 14, 14, 13, 12,
+       8, 15,  9, 12, 10, 13, 10, 11, 10, 14, 10, 12, 10, 13, 10, 11,
+      16, 16, 13, 14, 13, 14, 12, 12, 10, 16, 10, 13, 12, 15, 11, 11,
+      11, 16,  9, 12, 12, 14, 11, 11, 14, 16, 11, 13, 14, 16, 12, 11,
+      10, 16, 12, 14,  9, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      16, 16, 15, 16, 14, 14, 13, 12, 11, 16, 12, 14, 11, 14, 11, 11,
+      11, 16, 12, 14, 10, 13, 11, 11, 15, 16, 13, 15, 12, 14, 12, 11,
+      14, 16, 13, 14, 13, 16, 12, 12, 12, 16, 12, 13, 12, 14, 11, 11,
+      14, 16, 11, 12, 12, 13, 10, 10,  9, 16, 10, 14, 11, 15, 12, 12,
+      12, 16, 11, 13, 12, 15, 12, 12, 16, 16, 14, 13, 15, 15, 13, 12,
+      10, 16, 10, 14, 11, 15, 11, 12, 12, 16, 11, 13, 12, 14, 12, 12,
+      16, 16, 14, 13, 15, 14, 13, 12, 11, 16,  9, 12, 12, 14, 11, 11,
+      13, 16, 11, 13, 13, 15, 11, 11, 16, 16, 14, 14, 16, 16, 12, 12,
+      10, 16, 10, 14, 11, 14, 11, 12, 12, 16, 11, 13, 12, 14, 12, 12,
+      16, 16, 14, 14, 15, 15, 13, 12, 10, 16, 10, 13, 11, 14, 11, 12,
+      11, 16, 11, 13, 11, 14, 11, 12, 16, 16, 14, 14, 14, 14, 13, 12,
+      11, 16, 10, 12, 12, 15, 11, 11, 12, 16,  9, 12, 12, 14, 10, 11,
+      16, 16, 12, 13, 14, 15, 11, 11, 11, 16, 12, 14, 10, 14, 11, 11,
+      13, 16, 12, 14, 12, 14, 11, 11, 16, 16, 15, 15, 14, 15, 12, 12,
+      11, 16, 12, 14, 11, 14, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      16, 16, 14, 14, 13, 14, 12, 11, 12, 16, 11, 13, 12, 14, 10, 10,
+      12, 15, 11, 12, 12, 13, 10, 10, 14, 15, 11, 11, 12, 12, 10,  9,
+    ], [
+       0,  8,  3,  8,  5,  9,  7,  8,  5, 10,  6, 10,  8, 11,  8,  9,
+      16, 16, 15, 16, 16, 16, 11, 11,  2, 10,  4,  9,  7, 10,  7,  8,
+       7, 16,  7, 10,  9, 11,  8,  9, 16, 16, 15, 16, 16, 16, 11, 11,
+       7, 16,  6, 11, 10, 16,  9, 10, 10, 16,  9, 11, 11, 16,  9, 10,
+      16, 16, 16, 16, 16, 16, 16, 11,  3, 10,  6,  9,  5, 10,  7,  9,
+       7, 16,  8, 10,  8, 11,  8,  9, 16, 16, 16, 16, 16, 16, 11, 11,
+       5, 11,  7, 10,  8, 11,  8,  9,  7, 14,  7, 10,  8, 11,  8,  9,
+      16, 16, 11, 16, 16, 16, 10, 11,  9, 16,  9, 11, 11, 16,  9, 10,
+      10, 16,  8, 11, 11, 16,  9, 10, 16, 16, 11, 16, 16, 16, 11, 10,
+       8, 16,  9, 16,  7, 16,  9, 10, 11, 16, 11, 16, 10, 16, 10, 10,
+      16, 16, 16, 16, 16, 16, 16, 11,  9, 16, 10, 16,  9, 16,  9, 10,
+      10, 16, 10, 16,  9, 16,  9, 10, 16, 16, 16, 16, 11, 16, 11, 11,
+      16, 16, 16, 16, 16, 16, 10, 10, 11, 16, 11, 16, 11, 16, 10, 10,
+      16, 16, 11, 16, 11, 16, 10,  9, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       1, 10,  6, 10,  7, 11,  9, 10,  8, 12,  9, 12,  9, 12, 10, 10,
+      15, 16, 14, 15, 14, 16, 13, 12,  5, 12,  7, 11,  8, 11,  9, 10,
+       9, 13,  9, 12, 10, 12, 10, 10, 16, 16, 14, 15, 13, 16, 13, 12,
+      10, 15, 10, 13, 12, 14, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11,
+      16, 16, 14, 16, 14, 16, 13, 12,  5, 12,  8, 11,  7, 11,  9, 10,
+       9, 13, 10, 12,  9, 12, 10, 10, 14, 16, 14, 15, 13, 14, 13, 12,
+       7, 13,  9, 12,  9, 12, 10, 10,  9, 13,  9, 12,  9, 12, 10, 10,
+      14, 16, 13, 14, 13, 15, 12, 12, 11, 16, 11, 13, 12, 14, 11, 11,
+      12, 16, 11, 14, 12, 14, 11, 11, 16, 16, 14, 16, 14, 16, 13, 12,
+      10, 16, 11, 14, 10, 13, 11, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      15, 16, 15, 16, 14, 16, 13, 12, 11, 16, 12, 14, 11, 14, 11, 12,
+      12, 16, 12, 14, 11, 14, 11, 11, 15, 16, 14, 16, 13, 16, 13, 12,
+      13, 16, 13, 16, 13, 16, 12, 12, 13, 16, 13, 16, 13, 16, 12, 12,
+      16, 16, 14, 15, 14, 16, 13, 12,  4, 11,  7, 10,  7, 11,  9, 10,
+       9, 13,  9, 11,  9, 12, 10, 10, 15, 16, 14, 15, 14, 15, 13, 12,
+       6, 12,  7, 11,  8, 11,  9, 10,  9, 13,  9, 12, 10, 12, 10, 10,
+      15, 16, 13, 14, 14, 15, 12, 12, 10, 14, 10, 12, 12, 13, 11, 11,
+      12, 16, 11, 13, 12, 14, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12,
+       6, 12,  8, 11,  8, 11,  9, 10,  9, 13, 10, 12,  9, 12, 10, 10,
+      16, 16, 14, 15, 13, 14, 12, 12,  8, 13,  9, 11,  9, 12,  9, 10,
+       9, 13,  9, 12,  9, 12,  9, 10, 14, 16, 13, 14, 13, 14, 12, 11,
+      11, 15, 11, 13, 12, 14, 11, 11, 11, 16, 10, 13, 12, 14, 11, 11,
+      15, 16, 13, 15, 14, 16, 12, 11, 10, 16, 12, 13, 10, 13, 11, 11,
+      11, 16, 12, 14, 10, 13, 11, 11, 16, 16, 14, 16, 13, 16, 13, 12,
+      11, 16, 12, 14, 10, 14, 11, 11, 11, 16, 12, 14, 10, 13, 11, 11,
+      16, 16, 14, 16, 12, 15, 12, 11, 13, 16, 13, 15, 13, 15, 12, 12,
+      13, 16, 12, 15, 12, 15, 12, 11, 15, 16, 13, 16, 13, 16, 12, 11,
+       8, 14,  9, 12, 10, 13, 11, 11, 11, 16, 11, 13, 11, 13, 11, 11,
+      16, 16, 16, 16, 16, 16, 14, 13,  9, 14, 10, 12, 10, 13, 11, 11,
+      11, 16, 11, 13, 12, 13, 11, 11, 16, 16, 15, 16, 15, 16, 14, 12,
+      11, 16, 11, 13, 12, 14, 12, 11, 13, 16, 12, 14, 13, 14, 12, 11,
+      16, 16, 15, 16, 16, 16, 14, 13,  9, 14, 10, 13, 10, 13, 11, 11,
+      11, 16, 11, 13, 11, 13, 11, 11, 16, 16, 15, 16, 14, 15, 14, 13,
+       9, 14, 10, 13, 10, 13, 11, 11, 11, 15, 11, 13, 11, 13, 11, 11,
+      16, 16, 14, 16, 14, 16, 13, 12, 12, 16, 12, 14, 13, 14, 12, 11,
+      12, 16, 11, 14, 12, 15, 12, 11, 16, 16, 13, 16, 15, 16, 13, 11,
+      11, 16, 12, 14, 11, 14, 12, 11, 13, 16, 13, 15, 12, 14, 12, 12,
+      16, 16, 16, 16, 14, 16, 14, 13, 12, 16, 13, 15, 11, 14, 12, 12,
+      12, 16, 13, 14, 11, 15, 12, 11, 16, 16, 15, 16, 13, 15, 13, 12,
+      13, 16, 13, 15, 13, 16, 12, 12, 13, 16, 13, 15, 13, 15, 12, 12,
+      15, 16, 13, 16, 13, 15, 11, 10, 10, 16, 12, 14, 12, 15, 12, 12,
+      14, 16, 13, 15, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 15, 13,
+      10, 16, 12, 14, 12, 15, 12, 12, 13, 16, 13, 15, 13, 15, 13, 12,
+      16, 16, 16, 16, 16, 16, 14, 13, 11, 16, 12, 15, 13, 16, 12, 12,
+      14, 16, 13, 16, 13, 16, 12, 12, 16, 16, 15, 16, 15, 16, 14, 12,
+      11, 16, 12, 14, 12, 16, 12, 12, 14, 16, 13, 15, 13, 15, 13, 12,
+      16, 16, 16, 16, 16, 16, 15, 13, 11, 16, 12, 14, 12, 15, 12, 12,
+      13, 16, 12, 14, 12, 15, 12, 12, 16, 16, 16, 16, 16, 16, 14, 12,
+      12, 16, 12, 15, 13, 16, 12, 12, 13, 16, 12, 15, 13, 15, 12, 11,
+      16, 16, 14, 16, 15, 16, 13, 12, 12, 16, 13, 16, 12, 16, 12, 12,
+      15, 16, 14, 16, 13, 16, 12, 12, 16, 16, 16, 16, 16, 16, 14, 13,
+      12, 16, 13, 15, 12, 16, 12, 12, 13, 16, 13, 15, 12, 15, 12, 12,
+      16, 16, 15, 16, 14, 16, 13, 12, 13, 16, 13, 16, 12, 16, 12, 12,
+      13, 16, 12, 16, 12, 15, 12, 12, 14, 16, 12, 14, 12, 14, 11, 10,
+    ],
+  ], [
+    [
+       0, 16,  6, 16,  8, 16, 16, 16,  9, 16, 11, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 16,  7, 16, 11, 16, 16, 16,
+      10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 10, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  5, 16, 10, 16,  9, 16, 16, 16,
+      10, 16, 13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 11, 16, 12, 16, 16, 16, 10, 16, 12, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 16,  7, 16,  8, 16, 13, 16,
+       9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       4, 16,  7, 16, 11, 16, 13, 16,  9, 16, 11, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16,  9, 16, 16, 16, 16, 16,
+      13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       4, 16, 10, 16,  8, 16, 16, 16, 10, 16, 12, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 16, 10, 16, 11, 16, 16, 16,
+       9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 12, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 16, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       4, 16,  8, 16, 10, 16, 16, 16, 10, 16, 11, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16,  8, 16, 11, 16, 16, 16,
+      10, 16, 12, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16,  9, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 10, 16, 10, 16, 16, 16,
+      11, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 11, 16, 11, 16, 16, 16, 10, 16, 12, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16,
+      12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 16, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 12, 16, 16, 16,
+      12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 10, 16, 11, 16, 16, 16,
+      11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16,  9, 16, 11, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16,  9, 16, 13, 16, 12, 16,
+      13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16, 10, 16, 14, 16, 12, 16, 12, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 11, 16, 11, 16, 13, 16,
+      10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 10, 16, 13, 16, 12, 16, 12, 16, 11, 16, 16, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 12, 16, 10, 16, 13, 16,
+      16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 13, 16, 11, 16, 13, 16, 12, 16, 13, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 12, 16,
+      13, 16, 12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       0, 10,  4, 10,  5, 11,  9, 11,  6, 11,  8, 11,  8, 12, 10, 12,
+      15, 16, 13, 15, 14, 15, 13, 14,  4, 12,  5, 11,  8, 12,  9, 11,
+       7, 13,  8, 12,  9, 13, 10, 12, 15, 16, 13, 15, 14, 16, 13, 14,
+      10, 16,  9, 13, 12, 16, 11, 13, 11, 16, 10, 14, 13, 16, 12, 13,
+      16, 16, 14, 16, 15, 16, 14, 15,  4, 12,  7, 12,  6, 12,  9, 11,
+       8, 13,  9, 12,  9, 12, 10, 12, 15, 16, 13, 15, 14, 15, 13, 14,
+       7, 13,  8, 12,  9, 13, 10, 12,  8, 13,  9, 12,  9, 13, 10, 12,
+      14, 16, 13, 15, 13, 15, 13, 14, 12, 16, 11, 14, 13, 16, 12, 13,
+      12, 16, 11, 14, 13, 16, 12, 13, 16, 16, 14, 16, 15, 16, 14, 15,
+      10, 16, 12, 16, 10, 14, 12, 13, 12, 16, 13, 16, 11, 14, 12, 13,
+      16, 16, 16, 16, 15, 16, 14, 15, 12, 16, 13, 16, 11, 15, 12, 13,
+      13, 16, 13, 16, 12, 15, 12, 14, 16, 16, 16, 16, 14, 16, 13, 14,
+      16, 16, 14, 16, 14, 16, 13, 15, 16, 16, 14, 16, 14, 16, 13, 15,
+      16, 16, 16, 16, 16, 16, 14, 16,  2, 11,  5, 11,  6, 11,  9, 11,
+       7, 12,  8, 11,  9, 12, 10, 12, 15, 16, 14, 14, 14, 14, 13, 14,
+       4, 13,  6, 11,  8, 12,  9, 11,  8, 13,  8, 12, 10, 13, 10, 12,
+      15, 16, 13, 15, 14, 15, 13, 14,  9, 16,  8, 13, 12, 15, 11, 12,
+      11, 16, 10, 14, 13, 16, 12, 13, 16, 16, 14, 16, 16, 16, 14, 15,
+       5, 13,  8, 12,  7, 12,  9, 11,  8, 13,  9, 12,  9, 12, 10, 12,
+      16, 16, 14, 15, 14, 15, 13, 13,  7, 13,  8, 12,  9, 13, 10, 12,
+       8, 13,  8, 12,  9, 13, 10, 12, 14, 16, 13, 14, 13, 15, 12, 13,
+      11, 16, 10, 14, 13, 16, 12, 13, 11, 16, 10, 13, 12, 15, 11, 13,
+      14, 16, 12, 14, 14, 16, 13, 14, 10, 16, 12, 15,  9, 14, 11, 13,
+      12, 16, 12, 16, 11, 14, 12, 13, 16, 16, 15, 16, 16, 16, 14, 15,
+      11, 16, 12, 15, 11, 15, 12, 13, 12, 16, 12, 15, 11, 14, 12, 13,
+      16, 16, 14, 16, 13, 15, 13, 14, 15, 16, 14, 16, 14, 16, 13, 14,
+      14, 16, 13, 16, 14, 16, 13, 14, 16, 16, 14, 16, 14, 16, 13, 14,
+       7, 15,  8, 13,  9, 14, 11, 13, 10, 14, 10, 13, 11, 14, 12, 13,
+      16, 16, 15, 16, 15, 16, 15, 14,  7, 16,  8, 13, 10, 14, 11, 13,
+      11, 15, 10, 13, 12, 14, 12, 13, 16, 16, 16, 16, 16, 16, 15, 15,
+      10, 16,  9, 13, 13, 16, 12, 13, 13, 16, 11, 14, 14, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 16,  8, 16, 10, 14,  9, 14, 11, 13,
+      11, 16, 11, 14, 11, 14, 12, 13, 16, 16, 16, 16, 16, 16, 14, 15,
+       8, 16, 10, 14, 10, 14, 11, 13, 10, 15, 10, 14, 11, 14, 12, 13,
+      16, 16, 14, 16, 15, 16, 14, 14, 11, 16, 10, 14, 13, 16, 12, 13,
+      11, 16, 10, 13, 13, 16, 12, 13, 16, 16, 13, 16, 16, 16, 14, 14,
+      11, 16, 12, 16, 10, 15, 12, 13, 14, 16, 14, 16, 12, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 11, 16, 12, 14,
+      12, 16, 13, 16, 11, 14, 12, 13, 16, 16, 16, 16, 14, 16, 14, 14,
+      15, 16, 14, 16, 16, 16, 13, 14, 13, 16, 13, 15, 14, 16, 13, 14,
+      14, 16, 13, 14, 14, 15, 13, 14,  9, 16, 11, 16, 12, 16, 13, 14,
+      12, 16, 12, 15, 13, 16, 13, 14, 16, 16, 16, 15, 16, 16, 15, 15,
+      10, 16, 10, 16, 12, 16, 12, 14, 12, 16, 12, 14, 13, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 15, 11, 16, 10, 14, 14, 16, 12, 13,
+      14, 16, 12, 16, 14, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 15,
+      10, 16, 12, 16, 11, 16, 12, 14, 13, 16, 12, 15, 13, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 16, 15, 10, 16, 11, 16, 12, 16, 12, 14,
+      12, 16, 12, 15, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14,
+      11, 16, 10, 14, 14, 16, 12, 13, 13, 16, 11, 14, 14, 16, 12, 13,
+      16, 16, 15, 16, 16, 16, 14, 14, 12, 16, 13, 16, 11, 16, 12, 14,
+      15, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 16,
+      12, 16, 13, 16, 12, 16, 12, 14, 13, 16, 13, 16, 12, 16, 12, 13,
+      16, 16, 16, 16, 16, 16, 14, 15, 13, 16, 13, 16, 14, 16, 12, 13,
+      13, 16, 13, 14, 14, 16, 12, 13, 16, 16, 14, 14, 14, 15, 13, 13,
+    ], [
+       0,  9,  3,  9,  5,  9,  7,  9,  5, 10,  7, 11,  8, 11,  9, 10,
+      16, 16, 16, 16, 16, 16, 16, 16,  2, 11,  4, 10,  7, 11,  8, 10,
+       7, 16,  7, 11,  9, 16,  9, 11, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16,  7, 16, 11, 16, 10, 11, 11, 16, 10, 16, 16, 16, 11, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  2, 11,  6, 10,  6, 10,  8, 10,
+       7, 16,  8, 16,  8, 11,  9, 11, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 13,  7, 11,  8, 11,  9, 11,  6, 12,  8, 12,  8, 12,  9, 11,
+      16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 10, 16, 12, 16, 10, 13,
+      10, 16,  9, 16, 11, 16, 11, 12, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16,  8, 16, 10, 12, 11, 16, 12, 16, 10, 16, 11, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 10, 16, 11, 16, 10, 16, 11, 16,
+      11, 16, 12, 16, 10, 16, 11, 12, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       1, 10,  5, 10,  6, 10,  9, 10,  7, 12,  9, 12,  9, 12, 10, 10,
+      16, 16, 15, 16, 14, 16, 13, 13,  5, 12,  7, 11,  8, 11,  9, 10,
+       8, 13,  9, 12, 10, 12, 10, 11, 16, 16, 16, 16, 14, 16, 13, 12,
+      10, 16, 10, 13, 12, 14, 12, 12, 12, 16, 11, 14, 13, 15, 12, 12,
+      16, 16, 16, 15, 16, 16, 14, 13,  5, 12,  8, 11,  7, 11,  9, 10,
+       8, 13, 10, 12,  9, 12, 10, 10, 15, 16, 14, 15, 14, 14, 13, 13,
+       7, 13,  9, 12,  9, 12, 10, 10,  9, 13, 10, 13, 10, 13, 10, 10,
+      14, 16, 14, 15, 14, 16, 13, 12, 11, 16, 12, 14, 12, 15, 12, 12,
+      12, 16, 12, 15, 13, 16, 12, 12, 16, 16, 15, 16, 16, 16, 14, 13,
+      10, 16, 12, 14, 10, 14, 12, 12, 12, 16, 13, 14, 11, 14, 12, 12,
+      16, 16, 16, 16, 14, 16, 14, 13, 11, 16, 12, 14, 11, 14, 12, 12,
+      12, 16, 13, 16, 11, 15, 12, 12, 16, 16, 16, 16, 14, 16, 14, 13,
+      13, 16, 14, 16, 14, 16, 13, 13, 13, 16, 13, 16, 13, 16, 13, 12,
+      16, 16, 16, 16, 16, 16, 13, 13,  4, 11,  7, 10,  7, 11,  9, 10,
+       8, 12,  9, 12,  9, 12, 10, 11, 15, 16, 14, 15, 14, 16, 13, 13,
+       6, 12,  7, 11,  8, 11,  9, 10,  9, 13,  9, 12, 10, 12, 10, 10,
+      16, 16, 15, 16, 15, 16, 13, 12, 10, 16, 10, 13, 12, 14, 12, 11,
+      12, 16, 11, 14, 13, 14, 12, 12, 16, 16, 16, 14, 16, 16, 14, 13,
+       6, 12,  8, 11,  7, 11,  9, 10,  9, 14, 10, 12,  9, 12, 10, 10,
+      15, 16, 14, 16, 14, 16, 14, 13,  7, 13,  9, 12,  9, 12, 10, 10,
+       9, 13,  9, 12,  9, 12, 10, 10, 14, 16, 13, 14, 14, 16, 12, 11,
+      11, 16, 11, 14, 12, 14, 12, 12, 12, 16, 11, 14, 12, 14, 12, 11,
+      16, 16, 13, 16, 14, 16, 13, 12, 10, 16, 12, 14, 10, 14, 11, 11,
+      12, 16, 13, 14, 11, 14, 12, 12, 16, 16, 16, 16, 14, 16, 13, 13,
+      11, 16, 12, 16, 11, 14, 12, 12, 12, 16, 12, 14, 11, 14, 12, 11,
+      16, 16, 15, 16, 13, 15, 13, 12, 13, 16, 14, 16, 13, 16, 13, 12,
+      13, 16, 13, 16, 13, 16, 13, 12, 16, 16, 14, 16, 14, 16, 12, 11,
+       8, 13, 10, 12, 10, 13, 11, 11, 11, 14, 12, 14, 12, 14, 12, 12,
+      16, 16, 16, 16, 16, 16, 14, 13,  9, 14, 10, 13, 10, 13, 11, 11,
+      12, 16, 12, 13, 12, 13, 12, 11, 16, 16, 16, 16, 16, 16, 15, 14,
+      12, 16, 11, 14, 13, 15, 12, 12, 13, 16, 12, 15, 14, 15, 13, 12,
+      16, 16, 16, 16, 16, 16, 15, 13,  9, 14, 11, 13, 10, 13, 11, 11,
+      11, 16, 12, 14, 12, 14, 12, 12, 16, 16, 16, 16, 16, 16, 16, 13,
+      10, 15, 11, 13, 11, 14, 12, 11, 11, 16, 12, 14, 11, 14, 12, 11,
+      16, 16, 16, 16, 16, 16, 14, 12, 12, 16, 12, 14, 13, 15, 13, 12,
+      12, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 16, 16, 16, 14, 12,
+      12, 16, 13, 16, 11, 14, 12, 12, 14, 16, 14, 16, 12, 16, 13, 12,
+      16, 16, 16, 16, 16, 16, 16, 13, 12, 16, 13, 16, 12, 16, 13, 12,
+      12, 16, 13, 16, 12, 16, 12, 12, 16, 16, 16, 16, 14, 16, 14, 12,
+      14, 16, 14, 16, 14, 16, 14, 13, 13, 16, 13, 16, 13, 16, 13, 12,
+      16, 16, 13, 16, 13, 16, 12, 11,  9, 16, 12, 15, 13, 16, 13, 12,
+      13, 16, 14, 16, 14, 16, 14, 13, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 16, 12, 15, 12, 15, 13, 12, 13, 16, 14, 16, 13, 16, 13, 12,
+      16, 16, 16, 16, 16, 16, 16, 13, 12, 16, 12, 16, 13, 16, 13, 12,
+      14, 16, 13, 16, 14, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 13,
+      11, 16, 12, 15, 12, 16, 13, 12, 14, 16, 14, 16, 13, 16, 13, 13,
+      16, 16, 16, 16, 16, 16, 15, 13, 11, 16, 12, 16, 12, 16, 13, 12,
+      13, 16, 13, 15, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 15, 13,
+      12, 16, 12, 16, 13, 16, 13, 12, 13, 16, 12, 16, 13, 16, 13, 12,
+      16, 16, 14, 16, 16, 16, 14, 12, 12, 16, 14, 16, 11, 16, 13, 12,
+      14, 16, 14, 16, 13, 16, 13, 12, 16, 16, 16, 16, 16, 16, 16, 13,
+      12, 16, 13, 16, 12, 16, 13, 12, 13, 16, 13, 16, 12, 16, 13, 12,
+      16, 16, 16, 16, 14, 16, 14, 12, 13, 16, 13, 16, 13, 16, 13, 13,
+      13, 16, 12, 16, 12, 16, 12, 12, 14, 16, 13, 15, 13, 16, 12, 11,
+    ],
+  ],
+];
+
+const RV34_INTRA_SECONDPAT: &'static [[[u8; 108]; 2]; 5] = &[
+  [
+    [
+       0,  5, 10,  3,  6, 10,  7,  8,  9,  4,  6, 10,  6,  7,  9,  8,
+       8,  9,  8,  8,  9,  8,  9,  9,  9,  9,  8,  3,  6, 10,  4,  6,
+      10,  7,  7,  9,  5,  7, 10,  6,  7,  9,  7,  7,  8,  7,  8,  9,
+       8,  8,  9,  8,  8,  7,  6,  8, 10,  6,  8, 10,  7,  8,  9,  7,
+       8, 10,  7,  8, 10,  8,  8,  8,  8,  9,  9,  8,  8,  9,  9,  8,
+       7,  7,  8,  9,  7,  8,  9,  7,  7,  7,  8,  8,  9,  7,  8,  9,
+       7,  7,  7,  8,  8,  8,  7,  7,  7,  7,  6,  5,
+    ], [
+       0,  5, 11,  3,  6, 11,  8,  9, 11,  3,  6, 10,  6,  7, 11,  9,
+       9, 11,  7,  9, 11,  9,  9, 11, 10, 10, 11,  2,  6, 10,  4,  7,
+      10,  7,  9, 11,  4,  7, 11,  6,  7, 10,  9,  9, 11,  7,  9, 11,
+       8,  9, 10, 10, 10, 10,  5,  8, 11,  6,  8, 11,  8,  9, 11,  6,
+       8, 11,  7,  8, 11,  9,  9, 11,  8, 10, 11,  9,  9, 11, 10, 10,
+      10,  8,  9, 11,  8,  9, 11,  9,  9, 10,  8,  9, 11,  8,  9, 11,
+       9,  9, 10,  8,  9, 10,  9,  9, 10,  9,  9,  8,
+    ],
+  ], [
+    [
+       0,  5, 10,  4,  6, 10,  7,  8, 10,  4,  6, 10,  6,  7,  9,  8,
+       8,  9,  8,  8,  9,  8,  9,  9,  9,  9,  9,  2,  6, 10,  4,  6,
+      10,  7,  7,  9,  5,  7, 10,  6,  7,  9,  7,  7,  9,  7,  8,  9,
+       8,  8,  9,  9,  8,  8,  6,  8, 10,  6,  8, 10,  7,  8,  9,  6,
+       8, 10,  7,  8, 10,  8,  8,  9,  8,  9, 10,  8,  8,  9,  9,  9,
+       8,  8,  8, 10,  7,  8,  9,  7,  8,  8,  7,  8, 10,  7,  8,  9,
+       7,  7,  8,  8,  8,  9,  8,  8,  8,  7,  7,  6,
+    ], [
+       0,  5, 12,  4,  7, 12,  8, 10, 13,  4,  7, 12,  6,  8, 12, 10,
+      10, 12,  8,  9, 12, 10, 10, 12, 12, 12, 12,  1,  6, 12,  4,  7,
+      12,  8,  9, 12,  4,  7, 12,  6,  8, 11,  9, 10, 12,  8,  9, 12,
+       9, 10, 11, 11, 11, 12,  6,  8, 12,  7,  9, 12,  9, 10, 13,  6,
+       9, 12,  8,  9, 12, 10, 10, 12,  9, 10, 12, 10, 10, 12, 12, 12,
+      12,  8, 10, 12,  9, 10, 12, 10, 10, 12,  8, 10, 12,  9, 10, 12,
+      10, 10, 11,  9, 10, 12, 10, 10, 11, 11, 10, 10,
+    ],
+  ], [
+    [
+       0,  5, 10,  3,  6, 10,  7,  8, 11,  4,  6, 10,  6,  7, 10,  8,
+       9, 10,  8,  8, 10,  9,  9, 10, 10, 10, 10,  2,  6, 10,  4,  6,
+      10,  7,  8, 10,  4,  7, 10,  6,  7, 10,  8,  8, 10,  7,  8, 10,
+       8,  8,  9, 10,  9,  9,  5,  8, 11,  6,  8, 10,  7,  9, 10,  6,
+       8, 11,  7,  8, 10,  8,  8, 10,  8,  9, 11,  9,  9, 10, 10,  9,
+       9,  8,  9, 10,  8,  9, 10,  8,  9, 10,  8,  9, 10,  8,  8, 10,
+       8,  8,  9,  8,  9, 10,  8,  8,  9,  9,  8,  8,
+    ], [
+       0,  6, 13,  4,  7, 14,  9, 11, 14,  3,  7, 13,  7,  8, 13, 11,
+      11, 14,  8, 10, 13, 10, 11, 13, 13, 13, 14,  1,  6, 12,  4,  8,
+      13,  9, 10, 15,  4,  8, 13,  7,  8, 12, 11, 11, 14,  8, 10, 13,
+      10, 10, 13, 13, 13, 14,  5,  9, 13,  7,  9, 13, 10, 11, 14,  6,
+      10, 14,  8, 10, 14, 11, 11, 14,  9, 11, 14, 11, 11, 13, 13, 13,
+      14,  9, 10, 14,  9, 11, 13, 11, 12, 14,  9, 11, 13,  9, 11, 14,
+      11, 12, 13, 10, 12, 15, 11, 11, 13, 13, 12, 13,
+    ],
+  ], [
+    [
+       0,  5, 11,  3,  6, 11,  7,  9, 12,  3,  6, 11,  6,  7, 11,  9,
+       9, 11,  8,  9, 11,  9,  9, 11, 11, 11, 12,  2,  6, 11,  4,  6,
+      11,  7,  9, 11,  4,  7, 11,  5,  7, 10,  9,  9, 11,  7,  8, 11,
+       9,  9, 10, 11, 11, 11,  5,  8, 11,  6,  8, 11,  8,  9, 12,  6,
+       8, 11,  7,  8, 11,  9,  9, 11,  8,  9, 12,  9,  9, 11, 11, 11,
+      11,  8, 10, 12,  8, 10, 11,  9, 10, 12,  8, 10, 12,  8,  9, 12,
+      10, 10, 12,  9, 10, 12,  9,  9, 11, 11, 10, 11,
+    ], [
+       0,  6, 13,  3,  8, 14, 10, 12, 16,  3,  8, 15,  7,  9, 15, 12,
+      13, 15,  9, 11, 15, 11, 12, 16, 14, 16, 16,  1,  7, 13,  4,  8,
+      14,  9, 11, 15,  4,  8, 14,  7,  9, 14, 12, 13, 15,  8, 10, 14,
+      11, 11, 14, 16, 14, 16,  6,  9, 14,  7, 10, 14, 11, 13, 15,  7,
+      10, 14,  9, 10, 13, 12, 12, 15, 10, 11, 14, 11, 11, 14, 14, 14,
+      16,  9, 11, 14, 10, 11, 14, 13, 14, 15,  9, 12, 14, 10, 12, 16,
+      13, 14, 16, 10, 13, 16, 12, 12, 14, 15, 14, 15,
+    ],
+  ], [
+    [
+       0,  6, 12,  3,  7, 12,  9, 11, 13,  4,  7, 12,  6,  8, 12, 10,
+      11, 13,  8, 10, 13, 10, 11, 13, 13, 13, 14,  1,  6, 12,  4,  7,
+      12,  9, 10, 14,  4,  7, 12,  6,  7, 12, 10, 11, 13,  8,  9, 13,
+      10, 10, 12, 13, 13, 14,  6,  9, 13,  7,  9, 13, 10, 12, 14,  7,
+       9, 13,  8, 10, 13, 11, 11, 14,  9, 11, 13, 11, 11, 14, 13, 13,
+      14, 10, 12, 14, 10, 12, 14, 12, 13, 15, 10, 12, 14, 10, 12, 14,
+      12, 13, 15, 11, 13, 15, 12, 12, 15, 14, 14, 14,
+    ], [
+       0,  6, 16,  3,  8, 16, 10, 13, 16,  3,  8, 16,  7,  9, 16, 13,
+      16, 16,  8, 10, 16, 11, 13, 16, 16, 16, 16,  1,  7, 14,  4,  8,
+      16, 10, 12, 16,  4,  8, 13,  7,  9, 16, 13, 14, 16,  8, 10, 16,
+      11, 11, 14, 16, 16, 16,  6,  9, 14,  8, 10, 14, 12, 16, 16,  6,
+      10, 13,  9, 11, 16, 13, 14, 16,  9, 12, 16, 12, 11, 16, 16, 16,
+      16, 10, 12, 16, 11, 12, 16, 16, 14, 16,  9, 12, 16, 11, 12, 16,
+      16, 15, 16, 10, 13, 16, 12, 13, 16, 16, 16, 16,
+    ],
+  ],
+];
+
+const RV34_INTRA_THIRDPAT: &'static [[[u8; 108]; 2]; 5] = &[
+  [
+    [
+       0,  5, 10,  3,  6, 10,  7,  8, 10,  4,  7, 10,  6,  7, 10,  8,
+       8, 10,  8,  9, 10,  9,  9, 10,  9,  9,  9,  2,  6, 10,  4,  7,
+      10,  7,  8,  9,  5,  7, 10,  6,  7, 10,  8,  8,  9,  8,  9, 10,
+       8,  8,  9,  9,  9,  8,  6,  8, 11,  6,  8, 10,  7,  8, 10,  6,
+       8, 11,  7,  8, 10,  8,  8,  9,  8,  9, 10,  9,  9, 10,  9,  9,
+       9,  7,  8, 10,  7,  8, 10,  7,  8,  8,  7,  8, 10,  7,  8,  9,
+       7,  8,  8,  8,  8,  9,  8,  8,  8,  7,  7,  7,
+    ], [
+       0,  4, 10,  3,  6, 10,  7,  8, 11,  3,  6, 10,  5,  7, 10,  9,
+       9, 11,  9, 10, 11,  9, 10, 11, 11, 11, 11,  2,  6, 10,  4,  6,
+      10,  7,  8, 10,  4,  7, 10,  6,  7, 10,  8,  9, 10,  8,  9, 11,
+       9,  9, 11, 10, 10, 11,  6,  8, 11,  6,  8, 11,  8,  9, 11,  7,
+       9, 11,  7,  8, 11,  9,  9, 11,  9, 10, 12, 10, 10, 12, 11, 11,
+      11,  8,  9, 11,  8,  9, 11,  9,  9, 11,  9, 10, 11,  9, 10, 11,
+       9, 10, 11, 10, 11, 12, 10, 10, 12, 10, 10, 10,
+    ],
+  ], [
+    [
+       0,  5, 10,  3,  6, 10,  7,  8, 10,  4,  7, 10,  6,  7, 10,  8,
+       9, 10,  8,  9, 11,  8,  9, 10, 10, 10, 10,  2,  6, 10,  4,  6,
+      10,  7,  8, 10,  4,  7, 10,  5,  7, 10,  8,  8, 10,  8,  9, 10,
+       8,  9, 10,  9,  9,  9,  5,  7, 11,  6,  8, 11,  7,  8, 11,  6,
+       8, 11,  7,  8, 10,  8,  9, 10,  8,  9, 11,  9,  9, 10, 10,  9,
+      10,  7,  8, 10,  7,  8, 10,  8,  9, 10,  8,  9, 10,  8,  9, 10,
+       8,  8, 10,  9,  9, 10,  9,  9, 10,  9,  9,  9,
+    ], [
+       0,  5, 11,  3,  6, 11,  8,  9, 12,  4,  7, 12,  6,  7, 12,  9,
+      10, 13, 10, 11, 13, 10, 11, 14, 12, 13, 14,  1,  6, 11,  4,  7,
+      11,  8,  9, 12,  5,  7, 11,  6,  8, 12,  9, 10, 13, 10, 11, 14,
+      10, 11, 13, 12, 12, 14,  6,  8, 12,  7,  9, 13,  9, 10, 14,  7,
+      10, 13,  8, 10, 12, 11, 11, 13, 11, 13, 14, 11, 12, 14, 13, 13,
+      15,  9, 10, 12,  9, 11, 14, 10, 11, 14, 11, 11, 13, 10, 11, 13,
+      11, 12, 14, 12, 14, 15, 13, 13, 14, 13, 13, 14,
+    ],
+  ], [
+    [
+       0,  5, 11,  3,  6, 11,  7,  9, 11,  4,  6, 11,  5,  7, 10,  9,
+       9, 11,  8,  9, 11,  9, 10, 11, 11, 11, 11,  2,  6, 10,  3,  6,
+      10,  7,  9, 11,  4,  7, 10,  5,  7, 10,  8,  9, 11,  8,  9, 11,
+       9,  9, 11, 11, 11, 11,  5,  8, 11,  6,  8, 11,  8, 10, 12,  6,
+       8, 11,  7,  8, 11,  9, 10, 11,  9, 10, 12,  9, 10, 11, 11, 11,
+      11,  8,  9, 11,  8, 10, 12,  9, 11, 12,  8, 10, 12,  9, 10, 12,
+      10, 11, 12, 10, 11, 12, 10, 10, 11, 11, 11, 11,
+    ], [
+       0,  5, 13,  2,  7, 16,  9, 11, 16,  4,  8, 16,  7,  9, 16, 12,
+      12, 16, 12, 16, 16, 12, 16, 16, 16, 16, 16,  1,  6, 13,  4,  8,
+      16,  9, 11, 16,  6,  9, 16,  7, 10, 16, 13, 13, 16, 13, 15, 16,
+      12, 16, 16, 16, 16, 16,  7,  9, 16,  8, 11, 15, 11, 13, 16, 10,
+      12, 16, 10, 12, 16, 16, 13, 16, 16, 16, 16, 14, 16, 16, 16, 16,
+      16, 12, 12, 16, 12, 16, 16, 16, 16, 16, 13, 14, 16, 12, 13, 16,
+      16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  6, 11,  3,  7, 11,  8, 10, 12,  4,  7, 11,  6,  8, 11, 10,
+      11, 12,  9, 10, 12, 10, 10, 12, 12, 12, 13,  1,  6, 11,  4,  7,
+      11,  8, 10, 12,  4,  7, 11,  6,  8, 11, 10, 10, 12,  9, 10, 12,
+      10, 10, 12, 13, 13, 13,  6,  8, 12,  7, 10, 12, 10, 12, 13,  7,
+       9, 12,  8, 10, 12, 11, 11, 13, 11, 12, 14, 11, 11, 13, 13, 13,
+      13,  9, 11, 13, 10, 12, 14, 12, 13, 15, 10, 12, 14, 11, 12, 14,
+      13, 13, 14, 12, 13, 15, 13, 13, 14, 14, 14, 14,
+    ], [
+       0,  5, 16,  2,  6, 16, 10, 14, 16,  4,  8, 16,  7,  9, 16, 11,
+      16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16,  1,  6, 12,  4,  8,
+      12, 12, 12, 16,  6,  8, 16,  8, 10, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 12, 16, 16,  7, 10, 16,  8, 11, 14, 16, 16, 16, 10,
+      12, 16, 10, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  5, 11,  3,  6, 11, 10, 10, 12,  3,  7, 11,  6,  8, 11, 11,
+      11, 12, 10, 10, 12, 11, 11, 13, 14, 13, 14,  1,  6, 11,  4,  7,
+      11, 10, 11, 13,  5,  7, 11,  7,  8, 11, 11, 11, 13, 10, 11, 13,
+      11, 11, 12, 13, 13, 14,  7, 10, 12,  9, 11, 13, 12, 13, 14,  9,
+      10, 13,  9, 10, 13, 12, 11, 13, 12, 13, 16, 12, 13, 13, 14, 14,
+      14, 11, 14, 16, 12, 14, 15, 14, 13, 16, 13, 13, 15, 13, 14, 16,
+      14, 13, 16, 13, 13, 16, 13, 14, 15, 15, 14, 15,
+    ], [
+       0,  4, 16,  2,  7, 16, 10, 16, 16,  4, 10, 16,  7, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  1,  6, 13,  4, 11,
+      16, 16, 16, 16,  6, 10, 16,  8, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16,  8, 16, 16, 10, 16, 16, 16, 16, 16, 10,
+      16, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ],
+];
+
+const RV34_INTRA_COEFFS: &'static [[u8; 32]; 5] = &[
+  [
+    1,  3,  3,  4,  4,  5,  6,  6,  6,  7,  7,  7,  8,  8,  9,  9,
+    9,  9, 10, 10, 10, 11, 11, 11, 10, 10, 10, 12, 13, 14, 15, 15,
+  ], [
+    1,  2,  3,  5,  5,  6,  6,  7,  7,  8,  8,  9, 10, 10, 10, 11,
+   11, 11, 12, 12, 13, 13, 13, 13, 13, 13, 13, 14, 16, 16, 16, 16,
+  ], [
+    1,  2,  3,  4,  5,  6,  8,  8,  9,  9, 10, 10, 11, 12, 12, 12,
+   13, 13, 14, 14, 14, 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16,
+  ], [
+    1,  2,  3,  4,  5,  6,  8,  8,  9,  9, 10, 10, 11, 12, 12, 12,
+   13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 14, 12, 16, 16, 16, 16,
+  ], [
+    1,  2,  3,  4,  5,  7,  7,  8,  8,  9, 10, 10, 12, 11, 13, 12,
+   15, 13, 14, 13, 12, 15, 14, 13, 12, 12, 10, 11, 16, 16, 16, 16,
+  ]
+];
+
+const RV34_INTER_CBPPAT: &'static [[u8; 1296]; 7] = &[
+[
+  7,  9,  9,  8,  9,  8,  9,  8,  9,  9,  8,  8,  8,  8,  8,  4,
+  7, 10, 11, 10, 11, 10, 12, 10, 12, 11, 11, 10, 11, 10, 10,  7,
+ 10, 11, 15, 12, 15, 12, 15, 12, 15, 14, 14, 12, 14, 12, 14,  9,
+  7, 11, 10, 10, 12, 11, 11, 10, 11, 12, 10, 10, 11, 10, 10,  7,
+  8, 12, 12, 11, 13, 12, 12, 10, 13, 13, 12, 10, 12, 11, 11,  7,
+ 11, 13, 15, 11, 15, 13, 15, 12, 16, 14, 14, 12, 15, 13, 13,  9,
+ 10, 15, 11, 12, 15, 14, 14, 12, 15, 15, 12, 12, 14, 14, 12,  9,
+ 11, 15, 13, 12, 16, 15, 14, 12, 15, 15, 13, 12, 15, 14, 13,  9,
+ 13, 15, 14, 10, 16, 15, 16, 11, 16, 16, 15, 12, 16, 15, 15,  9,
+  7, 11, 11, 11, 11, 10, 11, 10, 11, 12, 11, 10, 10, 10, 10,  7,
+  9, 12, 13, 12, 12, 11, 13, 10, 13, 13, 12, 11, 12, 10, 11,  7,
+ 12, 13, 16, 14, 15, 12, 16, 12, 16, 15, 15, 13, 15, 12, 14,  9,
+  9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11,  7,
+  9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 13, 11, 12, 11, 11,  7,
+ 12, 14, 15, 13, 16, 13, 15, 11, 16, 14, 15, 12, 15, 12, 13,  8,
+ 12, 16, 14, 14, 16, 15, 15, 13, 16, 15, 14, 13, 15, 14, 13,  9,
+ 12, 15, 14, 13, 15, 14, 15, 12, 16, 15, 14, 12, 14, 13, 13,  8,
+ 13, 16, 16, 12, 16, 14, 16, 11, 16, 16, 15, 12, 16, 14, 14,  8,
+ 10, 15, 15, 15, 12, 12, 14, 12, 14, 15, 15, 14, 12, 12, 13,  9,
+ 11, 15, 16, 14, 13, 12, 15, 12, 16, 15, 15, 14, 14, 12, 13,  9,
+ 14, 15, 16, 16, 15, 11, 16, 12, 16, 16, 16, 15, 16, 12, 15,  9,
+ 12, 16, 16, 15, 14, 14, 14, 13, 16, 16, 15, 14, 14, 13, 13,  9,
+ 12, 15, 15, 14, 14, 13, 15, 12, 16, 15, 14, 13, 14, 13, 13,  8,
+ 13, 16, 16, 15, 16, 12, 16, 11, 16, 16, 16, 14, 16, 13, 14,  8,
+ 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 15, 16, 15, 14, 11,
+ 13, 16, 16, 15, 16, 15, 15, 12, 16, 16, 16, 14, 15, 14, 14,  9,
+ 14, 16, 16, 13, 16, 14, 16, 10, 16, 16, 16, 13, 16, 14, 14,  8,
+  7, 12, 11, 11, 11, 11, 12, 10, 11, 11, 10, 10, 10, 10, 10,  7,
+  9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11,  8,
+ 12, 14, 16, 14, 16, 14, 16, 13, 16, 14, 15, 13, 15, 13, 14,  9,
+  9, 13, 12, 12, 13, 12, 13, 11, 12, 13, 11, 10, 12, 11, 11,  7,
+  9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11,  7,
+ 12, 14, 16, 13, 16, 14, 15, 12, 15, 15, 14, 12, 15, 13, 13,  8,
+ 11, 15, 13, 14, 15, 15, 14, 13, 15, 15, 12, 12, 14, 14, 12,  9,
+ 11, 15, 14, 13, 15, 14, 14, 12, 15, 14, 13, 11, 14, 13, 12,  8,
+ 13, 16, 15, 12, 16, 15, 16, 12, 16, 16, 14, 11, 15, 14, 14,  8,
+  8, 13, 13, 12, 12, 12, 13, 11, 12, 13, 12, 11, 11, 10, 10,  7,
+  9, 13, 14, 12, 13, 12, 13, 11, 13, 13, 13, 11, 12, 11, 11,  7,
+ 12, 14, 16, 14, 15, 13, 15, 12, 15, 15, 15, 13, 14, 12, 13,  8,
+  9, 13, 13, 12, 13, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11,  7,
+  9, 13, 12, 12, 13, 12, 12, 10, 13, 13, 12, 10, 12, 10, 10,  6,
+ 11, 14, 14, 12, 14, 12, 14, 11, 14, 14, 13, 11, 13, 11, 12,  7,
+ 12, 16, 14, 14, 15, 15, 14, 13, 15, 15, 13, 12, 14, 13, 12,  8,
+ 11, 14, 13, 12, 14, 13, 13, 11, 14, 14, 13, 11, 13, 12, 11,  7,
+ 11, 14, 14, 12, 15, 13, 14, 11, 15, 14, 13, 11, 14, 12, 12,  6,
+ 11, 16, 15, 15, 13, 14, 15, 13, 14, 15, 15, 13, 12, 12, 12,  9,
+ 12, 15, 15, 14, 14, 13, 15, 12, 15, 15, 14, 13, 13, 11, 12,  8,
+ 13, 16, 16, 15, 16, 13, 16, 13, 16, 16, 15, 14, 14, 12, 14,  8,
+ 11, 16, 15, 14, 14, 14, 14, 13, 15, 15, 14, 13, 13, 12, 12,  8,
+ 11, 14, 14, 13, 13, 12, 14, 11, 14, 14, 13, 12, 12, 11, 11,  7,
+ 12, 14, 15, 13, 14, 12, 14, 11, 15, 14, 14, 12, 13, 11, 12,  7,
+ 13, 16, 16, 16, 16, 15, 16, 14, 16, 16, 15, 14, 15, 14, 13,  9,
+ 12, 15, 14, 13, 15, 13, 14, 12, 15, 15, 13, 12, 13, 12, 12,  7,
+ 11, 15, 14, 12, 14, 13, 14, 10, 15, 14, 13, 11, 13, 11, 11,  5,
+ 10, 15, 15, 15, 15, 14, 15, 13, 12, 14, 12, 12, 12, 13, 12,  9,
+ 12, 16, 16, 15, 16, 15, 16, 14, 14, 15, 14, 13, 14, 13, 13,  9,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 11,
+ 11, 15, 15, 14, 15, 15, 15, 14, 14, 15, 12, 12, 13, 13, 12,  9,
+ 12, 15, 15, 14, 16, 14, 15, 13, 14, 14, 13, 12, 14, 13, 12,  8,
+ 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 15, 12, 16, 14, 14,  9,
+ 13, 16, 14, 16, 16, 16, 16, 15, 15, 16, 11, 12, 16, 15, 12,  9,
+ 13, 16, 15, 14, 16, 15, 16, 14, 15, 16, 12, 11, 15, 14, 13,  8,
+ 13, 16, 16, 13, 16, 16, 16, 13, 16, 16, 13, 11, 16, 14, 14,  8,
+ 11, 15, 15, 15, 14, 14, 15, 13, 13, 15, 14, 13, 12, 12, 12,  9,
+ 11, 15, 16, 14, 15, 14, 15, 13, 14, 14, 14, 13, 13, 12, 13,  8,
+ 13, 16, 16, 16, 16, 15, 16, 14, 16, 16, 16, 13, 15, 12, 14,  9,
+ 11, 16, 15, 14, 14, 14, 15, 13, 14, 14, 13, 12, 13, 12, 11,  8,
+ 11, 14, 14, 13, 14, 13, 14, 12, 13, 13, 12, 11, 12, 11, 11,  7,
+ 12, 15, 15, 13, 15, 14, 15, 12, 15, 14, 14, 11, 13, 12, 12,  7,
+ 13, 16, 15, 15, 16, 16, 16, 14, 15, 16, 12, 12, 14, 14, 12,  8,
+ 11, 15, 14, 13, 15, 13, 14, 12, 14, 14, 12, 11, 13, 12, 11,  6,
+ 11, 14, 14, 12, 15, 13, 14, 11, 15, 14, 12, 10, 13, 11, 11,  5,
+ 12, 16, 16, 16, 15, 15, 16, 15, 14, 16, 15, 15, 10, 12, 12,  9,
+ 13, 16, 16, 16, 15, 14, 16, 13, 15, 15, 15, 14, 12, 11, 13,  8,
+ 14, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 14, 14, 11, 14,  8,
+ 13, 16, 16, 15, 15, 15, 15, 14, 15, 16, 14, 13, 12, 12, 11,  8,
+ 11, 15, 15, 13, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11,  6,
+ 11, 15, 15, 13, 15, 12, 14, 11, 14, 14, 13, 11, 12, 10, 11,  5,
+ 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 14, 14, 13, 11,  8,
+ 11, 14, 14, 13, 14, 13, 14, 11, 14, 14, 12, 11, 12, 11, 10,  5,
+ 10, 13, 13, 11, 13, 12, 13,  9, 13, 13, 12,  9, 12, 10, 10,  3,
+], [
+  5,  7,  7,  7,  7,  7,  8,  7,  7,  8,  7,  7,  7,  7,  7,  4,
+  7,  9, 11,  9, 11,  9, 11,  9, 11, 10, 10,  9, 10,  9, 10,  6,
+ 11, 11, 14, 11, 14, 11, 14, 11, 15, 13, 14, 12, 14, 12, 13,  9,
+  6, 11, 10,  9, 11, 10, 11,  9, 11, 11,  9,  9, 10, 10,  9,  6,
+  8, 11, 11, 10, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11,  7,
+ 11, 13, 14, 11, 15, 13, 15, 11, 15, 14, 14, 12, 14, 13, 13,  9,
+ 10, 14, 11, 11, 15, 14, 13, 12, 14, 14, 11, 11, 14, 13, 12,  9,
+ 11, 14, 13, 11, 15, 14, 14, 11, 15, 15, 13, 11, 14, 14, 13,  9,
+ 12, 14, 14, 10, 16, 15, 16, 11, 16, 16, 15, 11, 16, 15, 14,  9,
+  6, 10, 11, 10, 10,  9, 11,  9, 10, 11, 10, 10,  9,  9,  9,  6,
+  9, 12, 12, 11, 12, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11,  7,
+ 12, 13, 15, 13, 14, 11, 15, 11, 15, 15, 14, 13, 14, 12, 14,  9,
+  9, 12, 12, 11, 12, 11, 12, 11, 12, 13, 11, 11, 12, 11, 11,  7,
+  9, 12, 12, 11, 13, 11, 12, 10, 13, 13, 12, 11, 12, 11, 11,  7,
+ 12, 14, 15, 12, 15, 12, 14, 11, 15, 15, 14, 12, 14, 13, 13,  8,
+ 12, 15, 14, 13, 15, 14, 14, 13, 16, 16, 14, 13, 15, 14, 13,  9,
+ 12, 15, 14, 13, 15, 14, 14, 12, 15, 15, 13, 12, 14, 13, 13,  9,
+ 13, 15, 15, 12, 16, 14, 15, 11, 16, 16, 15, 12, 15, 14, 14,  9,
+ 10, 14, 14, 14, 12, 11, 13, 12, 14, 15, 14, 13, 12, 11, 12,  9,
+ 12, 14, 15, 14, 13, 11, 14, 12, 15, 15, 15, 14, 13, 11, 13,  9,
+ 13, 15, 16, 15, 14, 11, 16, 11, 16, 16, 16, 14, 15, 12, 15,  9,
+ 12, 15, 15, 14, 14, 14, 14, 13, 15, 15, 14, 14, 14, 13, 13,  9,
+ 12, 15, 15, 14, 14, 13, 14, 12, 15, 15, 14, 13, 14, 13, 13,  9,
+ 13, 15, 16, 14, 15, 13, 16, 11, 16, 16, 15, 14, 15, 13, 14,  9,
+ 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 16, 16, 16, 14, 11,
+ 14, 16, 16, 14, 16, 15, 15, 12, 16, 16, 16, 14, 15, 14, 14,  9,
+ 14, 16, 16, 14, 16, 14, 16, 11, 16, 16, 16, 14, 16, 14, 14,  9,
+  6, 11, 10, 10, 10, 10, 11, 10, 10, 11,  9,  9,  9,  9,  9,  6,
+  9, 12, 12, 11, 13, 11, 13, 11, 12, 12, 11, 11, 12, 11, 11,  7,
+ 12, 14, 16, 13, 16, 14, 16, 13, 15, 14, 15, 12, 15, 13, 14,  9,
+  8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10,  7,
+  9, 12, 12, 11, 13, 12, 13, 11, 13, 12, 11, 10, 12, 11, 11,  7,
+ 12, 14, 15, 12, 15, 14, 15, 12, 15, 14, 14, 12, 14, 13, 13,  9,
+ 11, 15, 13, 13, 15, 14, 14, 13, 14, 15, 11, 11, 14, 14, 12,  9,
+ 11, 14, 13, 12, 15, 14, 14, 12, 14, 14, 12, 11, 14, 13, 12,  8,
+ 13, 15, 15, 12, 16, 15, 15, 12, 15, 15, 14, 11, 15, 14, 14,  8,
+  8, 12, 12, 11, 11, 11, 12, 11, 11, 12, 11, 11, 10, 10, 10,  7,
+  9, 13, 13, 12, 13, 11, 13, 11, 12, 13, 12, 11, 11, 10, 11,  7,
+ 12, 14, 15, 14, 15, 13, 15, 12, 15, 14, 14, 13, 14, 12, 13,  9,
+  9, 13, 12, 12, 12, 12, 12, 11, 12, 13, 11, 11, 11, 11, 10,  7,
+  9, 12, 12, 11, 12, 11, 12, 10, 12, 12, 11, 10, 11, 10, 10,  7,
+ 11, 13, 14, 12, 14, 12, 14, 11, 14, 13, 13, 11, 13, 11, 12,  7,
+ 12, 15, 14, 13, 15, 14, 14, 13, 15, 15, 13, 12, 13, 13, 12,  9,
+ 11, 14, 13, 12, 14, 13, 13, 11, 14, 14, 12, 11, 13, 12, 11,  7,
+ 11, 14, 14, 12, 14, 13, 14, 11, 14, 14, 13, 11, 13, 12, 12,  7,
+ 11, 15, 15, 14, 13, 13, 14, 13, 14, 15, 14, 13, 11, 11, 12,  9,
+ 12, 15, 15, 14, 14, 12, 14, 12, 14, 14, 14, 13, 12, 11, 12,  8,
+ 13, 16, 16, 15, 15, 12, 16, 13, 16, 15, 15, 14, 14, 12, 14,  9,
+ 12, 15, 15, 14, 14, 14, 14, 13, 15, 15, 14, 13, 12, 12, 12,  9,
+ 11, 14, 14, 13, 13, 12, 13, 11, 14, 13, 13, 12, 12, 11, 11,  7,
+ 12, 14, 15, 13, 14, 12, 14, 11, 15, 14, 13, 12, 13, 11, 12,  7,
+ 13, 16, 16, 15, 16, 15, 15, 14, 16, 16, 15, 14, 14, 14, 12,  9,
+ 12, 15, 14, 13, 14, 13, 14, 12, 15, 14, 13, 12, 13, 12, 12,  8,
+ 12, 14, 14, 13, 15, 13, 14, 11, 14, 14, 13, 12, 13, 12, 12,  6,
+ 10, 14, 14, 13, 14, 14, 14, 13, 12, 13, 12, 12, 12, 12, 11,  9,
+ 12, 15, 15, 14, 15, 14, 16, 14, 14, 14, 13, 12, 14, 13, 13,  9,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 16, 11,
+ 11, 15, 14, 14, 15, 14, 14, 14, 13, 14, 11, 12, 13, 13, 12,  9,
+ 12, 15, 14, 14, 15, 14, 15, 13, 14, 14, 13, 12, 14, 13, 13,  9,
+ 13, 16, 16, 14, 16, 15, 16, 14, 16, 15, 15, 12, 16, 14, 14,  9,
+ 13, 16, 14, 15, 16, 16, 16, 14, 14, 16, 11, 12, 15, 14, 12,  9,
+ 13, 16, 15, 14, 16, 15, 16, 14, 15, 15, 12, 11, 15, 14, 13,  9,
+ 14, 16, 16, 13, 16, 16, 16, 14, 16, 15, 13, 11, 16, 14, 14,  9,
+ 11, 15, 15, 14, 14, 14, 14, 13, 13, 14, 13, 13, 11, 11, 11,  9,
+ 12, 15, 15, 14, 15, 14, 15, 13, 14, 14, 13, 13, 13, 12, 12,  9,
+ 13, 16, 16, 16, 16, 14, 16, 14, 16, 15, 16, 14, 15, 12, 14,  9,
+ 11, 15, 14, 14, 15, 14, 14, 13, 14, 14, 12, 12, 12, 12, 11,  8,
+ 11, 14, 14, 13, 14, 13, 13, 12, 13, 13, 12, 11, 12, 11, 11,  7,
+ 12, 14, 15, 13, 15, 13, 14, 13, 14, 14, 13, 12, 13, 12, 12,  8,
+ 13, 16, 15, 15, 16, 15, 15, 14, 15, 16, 12, 12, 14, 14, 11,  9,
+ 12, 15, 14, 13, 15, 13, 14, 12, 14, 14, 12, 11, 13, 12, 11,  7,
+ 12, 14, 14, 13, 15, 13, 14, 12, 15, 14, 13, 10, 13, 12, 12,  6,
+ 12, 16, 16, 15, 14, 14, 15, 14, 13, 15, 14, 14, 10, 11, 11,  9,
+ 13, 16, 16, 15, 15, 14, 15, 14, 15, 15, 15, 14, 12, 11, 12,  8,
+ 14, 16, 16, 16, 16, 14, 16, 14, 16, 15, 15, 14, 14, 11, 14,  8,
+ 12, 16, 16, 15, 15, 14, 15, 14, 14, 16, 14, 14, 12, 12, 11,  8,
+ 11, 14, 14, 13, 14, 13, 14, 12, 14, 14, 13, 12, 12, 11, 11,  7,
+ 12, 14, 15, 13, 14, 13, 14, 12, 14, 14, 13, 12, 13, 11, 12,  6,
+ 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 14, 13, 13, 13, 11,  8,
+ 12, 15, 15, 13, 15, 13, 14, 12, 14, 14, 13, 12, 13, 12, 10,  6,
+ 11, 14, 13, 12, 14, 12, 13, 10, 14, 13, 12, 10, 12, 10, 10,  4,
+], [
+  4,  6,  6,  6,  6,  6,  7,  6,  6,  7,  6,  6,  6,  6,  6,  3,
+  6,  9, 10,  9, 10,  9, 11,  9, 10, 10, 10,  9, 10,  9, 10,  6,
+ 10, 11, 14, 11, 14, 11, 14, 11, 14, 13, 14, 11, 14, 11, 13,  9,
+  6, 10,  9,  9, 10, 10, 10,  9, 10, 11,  9,  9, 10, 10,  9,  6,
+  8, 11, 11,  9, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11,  7,
+ 11, 13, 14, 11, 15, 13, 15, 11, 15, 14, 14, 11, 15, 13, 14,  9,
+ 10, 13, 11, 11, 14, 14, 13, 11, 14, 14, 11, 11, 13, 13, 11,  9,
+ 11, 14, 12, 11, 15, 14, 14, 11, 15, 15, 13, 11, 14, 14, 13,  9,
+ 12, 14, 13, 10, 16, 15, 16, 11, 16, 16, 14, 11, 16, 14, 14,  9,
+  6, 10, 10, 10,  9,  9, 10,  9, 10, 11, 10, 10,  9,  9,  9,  6,
+  8, 11, 12, 11, 11, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11,  7,
+ 11, 13, 15, 13, 14, 11, 15, 11, 15, 14, 14, 13, 14, 12, 14,  9,
+  8, 12, 12, 12, 12, 12, 12, 11, 12, 13, 11, 11, 11, 11, 11,  8,
+  9, 12, 12, 11, 12, 12, 13, 11, 13, 13, 12, 11, 12, 11, 11,  8,
+ 11, 14, 15, 13, 14, 13, 15, 11, 15, 15, 14, 13, 15, 13, 14,  9,
+ 12, 16, 14, 14, 15, 15, 14, 12, 15, 16, 14, 13, 14, 14, 13, 10,
+ 11, 15, 14, 13, 15, 14, 15, 12, 15, 16, 14, 13, 15, 14, 13,  9,
+ 13, 15, 15, 12, 16, 15, 16, 12, 16, 16, 15, 13, 15, 14, 14,  9,
+ 10, 14, 14, 14, 11, 11, 13, 11, 14, 14, 14, 13, 11, 11, 11,  9,
+ 11, 14, 15, 14, 13, 11, 14, 12, 15, 15, 15, 14, 13, 11, 13,  9,
+ 13, 14, 16, 15, 14, 11, 16, 12, 16, 16, 16, 14, 15, 12, 15, 10,
+ 12, 16, 15, 15, 14, 14, 14, 12, 16, 16, 14, 14, 14, 13, 13, 10,
+ 12, 15, 15, 14, 14, 13, 14, 12, 15, 16, 14, 14, 14, 13, 13,  9,
+ 13, 16, 16, 14, 16, 13, 16, 12, 16, 16, 16, 14, 16, 13, 15, 10,
+ 14, 16, 16, 16, 16, 16, 15, 14, 16, 16, 16, 16, 16, 16, 14, 11,
+ 13, 16, 16, 15, 16, 16, 16, 13, 16, 16, 16, 15, 16, 15, 14, 10,
+ 14, 16, 16, 14, 16, 14, 16, 12, 16, 16, 16, 15, 16, 15, 15, 10,
+  6, 10, 10, 10, 10, 10, 11, 10,  9, 10,  9,  9,  9,  9,  9,  6,
+  9, 12, 12, 11, 12, 11, 13, 11, 12, 12, 11, 10, 12, 11, 11,  8,
+ 12, 14, 15, 14, 15, 14, 16, 13, 15, 14, 14, 12, 15, 13, 14, 10,
+  8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10,  7,
+  9, 12, 12, 11, 13, 12, 13, 11, 12, 13, 11, 10, 12, 12, 11,  8,
+ 11, 14, 14, 13, 15, 14, 15, 13, 15, 14, 14, 12, 15, 13, 14,  9,
+ 11, 15, 12, 13, 15, 15, 14, 13, 14, 15, 11, 11, 14, 14, 12,  9,
+ 11, 14, 13, 13, 15, 14, 15, 13, 15, 15, 13, 11, 15, 14, 13,  9,
+ 13, 15, 15, 12, 16, 15, 16, 13, 16, 15, 14, 11, 16, 15, 14,  9,
+  8, 12, 12, 11, 11, 11, 12, 11, 11, 12, 11, 11,  9, 10, 10,  7,
+  9, 12, 13, 12, 12, 11, 13, 11, 12, 13, 12, 12, 11, 11, 11,  8,
+ 12, 14, 15, 14, 15, 13, 16, 13, 15, 14, 15, 13, 14, 12, 14,  9,
+  9, 13, 12, 12, 12, 12, 13, 12, 12, 13, 11, 11, 11, 11, 10,  8,
+  9, 12, 12, 12, 12, 12, 13, 11, 12, 13, 11, 11, 12, 11, 11,  7,
+ 11, 13, 14, 13, 14, 13, 15, 12, 14, 14, 14, 12, 14, 12, 13,  8,
+ 12, 15, 14, 14, 15, 15, 14, 13, 15, 16, 13, 13, 14, 14, 12,  9,
+ 11, 14, 13, 13, 14, 14, 14, 12, 14, 15, 13, 12, 14, 13, 12,  8,
+ 11, 14, 14, 13, 15, 14, 15, 12, 15, 15, 14, 12, 14, 13, 13,  8,
+ 11, 14, 14, 14, 13, 13, 14, 13, 13, 14, 14, 13, 11, 11, 11,  9,
+ 11, 15, 15, 14, 14, 13, 15, 13, 14, 15, 14, 14, 13, 11, 13,  9,
+ 13, 16, 16, 16, 15, 13, 16, 13, 16, 16, 16, 15, 15, 12, 15, 10,
+ 11, 15, 15, 15, 14, 14, 14, 13, 15, 15, 14, 14, 13, 13, 12,  9,
+ 11, 14, 14, 13, 13, 13, 14, 12, 14, 14, 13, 13, 13, 12, 12,  8,
+ 12, 15, 15, 14, 15, 13, 15, 12, 15, 15, 14, 13, 14, 12, 13,  8,
+ 13, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15, 15, 15, 15, 13, 10,
+ 12, 15, 15, 14, 15, 14, 15, 13, 15, 16, 14, 13, 14, 14, 13,  9,
+ 12, 15, 15, 14, 15, 14, 15, 12, 15, 15, 14, 13, 14, 13, 13,  8,
+ 10, 14, 13, 13, 14, 13, 14, 13, 11, 13, 11, 11, 11, 11, 11,  9,
+ 12, 15, 16, 14, 15, 14, 16, 14, 14, 14, 14, 13, 14, 13, 13, 10,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13, 16, 14, 16, 11,
+ 11, 15, 14, 14, 15, 14, 15, 14, 13, 14, 11, 12, 13, 13, 11,  9,
+ 12, 15, 15, 14, 15, 15, 16, 14, 14, 14, 13, 12, 14, 13, 13,  9,
+ 13, 16, 16, 15, 16, 16, 16, 15, 16, 15, 15, 12, 16, 14, 15, 10,
+ 12, 16, 14, 15, 16, 16, 16, 14, 14, 16, 11, 12, 14, 15, 12,  9,
+ 13, 16, 15, 14, 16, 16, 16, 14, 15, 16, 13, 12, 15, 15, 13,  9,
+ 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 14, 12, 16, 15, 15, 10,
+ 11, 14, 14, 14, 14, 14, 14, 13, 12, 14, 13, 13, 11, 11, 11,  9,
+ 11, 15, 15, 14, 14, 14, 16, 14, 14, 14, 14, 13, 13, 12, 13,  9,
+ 13, 16, 16, 16, 16, 15, 16, 15, 16, 15, 16, 14, 15, 13, 15, 10,
+ 11, 15, 15, 14, 14, 14, 15, 14, 14, 15, 13, 13, 12, 13, 11,  9,
+ 11, 14, 14, 13, 14, 14, 14, 13, 13, 14, 13, 12, 13, 12, 12,  8,
+ 12, 15, 15, 14, 16, 14, 16, 14, 15, 15, 15, 13, 14, 13, 14,  9,
+ 13, 16, 15, 16, 16, 16, 16, 15, 15, 16, 13, 13, 14, 14, 12,  9,
+ 12, 15, 14, 14, 15, 15, 15, 13, 14, 15, 13, 12, 14, 13, 12,  8,
+ 12, 15, 14, 14, 15, 15, 15, 13, 15, 15, 14, 12, 14, 13, 13,  8,
+ 12, 16, 15, 15, 13, 14, 15, 14, 13, 15, 14, 14, 10, 11, 11,  9,
+ 12, 16, 16, 15, 15, 14, 16, 14, 15, 15, 15, 14, 13, 12, 13,  9,
+ 14, 16, 16, 16, 16, 14, 16, 15, 16, 15, 16, 15, 14, 12, 15, 10,
+ 12, 16, 15, 15, 15, 15, 15, 14, 15, 16, 14, 14, 12, 13, 11,  9,
+ 11, 15, 15, 14, 14, 14, 15, 13, 14, 15, 14, 13, 13, 12, 12,  8,
+ 12, 15, 15, 14, 15, 14, 15, 13, 15, 15, 14, 13, 14, 12, 13,  8,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 14, 14, 14, 14, 11,  9,
+ 12, 15, 15, 14, 15, 15, 15, 13, 15, 15, 14, 13, 14, 13, 12,  8,
+ 11, 14, 14, 13, 14, 13, 14, 12, 13, 14, 13, 12, 13, 12, 12,  7,
+], [
+  2,  6,  6,  5,  6,  6,  7,  6,  6,  7,  6,  6,  6,  6,  6,  3,
+  6,  9, 10,  9, 10,  9, 11,  9, 10, 10, 10,  9, 10,  9, 10,  7,
+ 10, 11, 14, 11, 14, 11, 14, 11, 14, 13, 14, 12, 14, 12, 13,  9,
+  6, 10,  9,  9, 10, 10, 10,  9, 10, 11,  9,  9, 10, 10,  9,  7,
+  8, 11, 11,  9, 12, 11, 12, 10, 12, 12, 11, 10, 12, 11, 11,  8,
+ 11, 13, 14, 11, 16, 13, 15, 12, 16, 14, 14, 12, 15, 13, 14, 10,
+ 10, 13, 11, 11, 14, 14, 13, 11, 13, 14, 11, 11, 13, 13, 11,  9,
+ 11, 13, 13, 11, 15, 14, 14, 12, 15, 15, 13, 12, 15, 14, 13, 10,
+ 12, 14, 14, 11, 16, 15, 16, 12, 16, 16, 15, 12, 16, 15, 15, 10,
+  6, 10, 10, 10,  9,  9, 10,  9, 10, 11, 10, 10,  9,  9,  9,  7,
+  8, 11, 12, 11, 11, 10, 12, 10, 12, 12, 12, 11, 11, 10, 11,  8,
+ 12, 13, 16, 13, 14, 11, 16, 12, 16, 15, 15, 13, 14, 12, 14, 10,
+  9, 13, 12, 12, 12, 12, 12, 11, 13, 13, 12, 12, 12, 12, 11,  8,
+ 10, 13, 13, 12, 13, 12, 13, 11, 14, 14, 13, 12, 13, 12, 12,  9,
+ 12, 14, 16, 13, 15, 13, 15, 12, 16, 16, 16, 13, 16, 14, 14, 10,
+ 12, 16, 14, 14, 16, 15, 14, 13, 16, 16, 14, 14, 15, 15, 13, 11,
+ 12, 16, 15, 14, 16, 15, 15, 12, 16, 16, 15, 14, 16, 15, 14, 10,
+ 14, 16, 16, 14, 16, 15, 16, 13, 16, 16, 16, 14, 16, 16, 15, 11,
+ 10, 14, 14, 13, 11, 11, 13, 12, 14, 14, 13, 13, 11, 11, 12,  9,
+ 12, 14, 16, 14, 13, 11, 14, 12, 16, 15, 15, 14, 14, 12, 13, 10,
+ 13, 14, 16, 15, 14, 11, 16, 12, 16, 16, 16, 15, 16, 13, 15, 11,
+ 12, 16, 15, 15, 14, 14, 14, 13, 16, 16, 15, 15, 14, 14, 13, 11,
+ 13, 16, 16, 15, 14, 14, 15, 13, 16, 16, 16, 15, 15, 14, 14, 11,
+ 14, 16, 16, 15, 16, 14, 16, 13, 16, 16, 16, 15, 16, 14, 15, 11,
+ 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14, 12,
+ 15, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 15, 12,
+ 15, 16, 16, 15, 16, 15, 16, 13, 16, 16, 16, 16, 16, 16, 16, 11,
+  6, 10, 10, 10, 10, 10, 11, 10,  9, 10,  9,  9,  9,  9,  9,  7,
+  9, 12, 13, 12, 13, 12, 14, 12, 12, 12, 12, 11, 12, 11, 11,  8,
+ 12, 14, 16, 14, 16, 14, 16, 14, 15, 14, 15, 13, 16, 13, 14, 11,
+  8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 11, 10,  8,
+ 10, 13, 13, 12, 14, 13, 14, 12, 13, 13, 12, 11, 13, 12, 12,  9,
+ 12, 15, 15, 13, 16, 15, 16, 14, 16, 15, 15, 12, 16, 14, 15, 10,
+ 11, 15, 13, 13, 16, 15, 14, 13, 14, 15, 11, 12, 14, 14, 12, 10,
+ 12, 16, 14, 13, 16, 16, 16, 14, 16, 15, 13, 12, 15, 15, 14, 10,
+ 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 15, 13, 16, 16, 15, 11,
+  8, 12, 12, 12, 11, 11, 12, 11, 11, 12, 11, 11,  9, 10, 10,  8,
+ 10, 13, 14, 13, 13, 12, 14, 12, 13, 13, 13, 12, 12, 11, 12,  9,
+ 13, 15, 16, 15, 16, 14, 16, 14, 16, 15, 16, 14, 15, 13, 15, 11,
+ 10, 13, 13, 13, 13, 13, 13, 12, 13, 14, 12, 12, 12, 12, 11,  9,
+ 10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 13, 12, 12, 12, 12,  9,
+ 12, 15, 15, 14, 16, 14, 16, 13, 16, 15, 15, 13, 15, 13, 14, 10,
+ 13, 16, 15, 15, 16, 16, 15, 14, 16, 16, 13, 14, 15, 15, 12, 10,
+ 12, 16, 14, 14, 16, 16, 15, 13, 16, 16, 14, 13, 15, 14, 13, 10,
+ 13, 16, 16, 14, 16, 15, 16, 13, 16, 16, 16, 13, 16, 15, 15, 10,
+ 11, 15, 15, 14, 13, 13, 14, 13, 13, 15, 14, 14, 11, 12, 12, 10,
+ 12, 15, 16, 15, 14, 13, 16, 14, 16, 15, 16, 14, 13, 12, 13, 10,
+ 14, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16, 13, 16, 11,
+ 12, 16, 16, 16, 15, 15, 15, 14, 15, 16, 14, 14, 13, 14, 12, 10,
+ 12, 16, 16, 15, 15, 14, 16, 13, 16, 16, 15, 14, 14, 13, 13, 10,
+ 13, 16, 16, 15, 16, 14, 16, 13, 16, 16, 16, 15, 16, 14, 15, 10,
+ 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 13, 12,
+ 14, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 15, 16, 15, 14, 11,
+ 14, 16, 16, 15, 16, 16, 16, 13, 16, 16, 16, 15, 16, 15, 14, 10,
+ 10, 14, 13, 13, 13, 13, 14, 13, 11, 13, 11, 11, 11, 11, 11,  9,
+ 12, 15, 16, 15, 16, 15, 16, 14, 14, 14, 14, 13, 14, 13, 14, 11,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 14, 16, 12,
+ 11, 15, 14, 14, 15, 15, 15, 14, 13, 14, 11, 12, 13, 13, 12, 10,
+ 13, 16, 15, 15, 16, 16, 16, 15, 15, 15, 13, 12, 15, 14, 13, 10,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 12,
+ 13, 16, 14, 15, 16, 16, 16, 15, 14, 16, 11, 12, 15, 15, 12, 10,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 16, 16, 14, 11,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 11,
+ 11, 15, 15, 14, 13, 14, 14, 14, 13, 14, 13, 13, 11, 12, 11, 10,
+ 12, 16, 16, 16, 16, 15, 16, 15, 15, 15, 15, 14, 13, 12, 14, 10,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 16, 12,
+ 12, 16, 15, 15, 16, 16, 16, 14, 14, 15, 13, 13, 13, 13, 12, 10,
+ 12, 16, 16, 15, 15, 15, 16, 14, 14, 15, 14, 13, 14, 13, 13, 10,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 11,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 15, 15, 12, 11,
+ 13, 16, 16, 15, 16, 16, 16, 14, 16, 16, 14, 13, 16, 14, 13, 10,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 14, 15, 10,
+ 12, 16, 16, 15, 14, 15, 16, 14, 13, 15, 14, 14, 11, 12, 12, 10,
+ 13, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 15, 13, 12, 14, 11,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 11,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 15, 15, 13, 14, 12, 11,
+ 13, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 14, 13, 13, 10,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 15, 14, 14, 10,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 15, 16, 13, 11,
+ 14, 16, 16, 16, 16, 16, 16, 14, 16, 16, 15, 14, 15, 14, 13, 10,
+ 12, 15, 15, 14, 15, 14, 16, 14, 14, 16, 15, 13, 14, 13, 13,  9,
+], [
+  2,  5,  5,  5,  5,  5,  6,  6,  5,  6,  5,  6,  5,  6,  6,  4,
+  6,  8, 10,  8, 10,  9, 11,  9, 10, 10, 10,  9, 10,  9, 10,  8,
+ 10, 11, 13, 11, 13, 11, 14, 11, 14, 13, 13, 12, 13, 12, 13, 10,
+  6, 10,  8,  9, 10, 10, 10,  9, 10, 11,  9,  9, 10, 10,  9,  7,
+  8, 11, 11, 10, 12, 11, 12, 10, 12, 12, 11, 10, 12, 12, 11,  9,
+ 11, 13, 14, 11, 15, 14, 15, 12, 16, 14, 14, 12, 15, 14, 14, 11,
+ 10, 13, 11, 11, 14, 13, 13, 12, 13, 14, 11, 11, 13, 13, 12, 10,
+ 11, 14, 13, 11, 16, 14, 14, 12, 15, 15, 14, 12, 15, 14, 14, 11,
+ 12, 14, 14, 11, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 15, 12,
+  6, 10, 10, 10,  8,  9, 10,  9, 10, 11, 10, 10,  9,  9,  9,  8,
+  8, 11, 12, 12, 11, 10, 12, 11, 12, 12, 12, 12, 12, 11, 12,  9,
+ 11, 13, 16, 14, 14, 12, 15, 12, 16, 15, 16, 14, 14, 13, 14, 11,
+  9, 13, 12, 12, 12, 12, 12, 11, 13, 13, 12, 12, 12, 12, 11, 10,
+ 10, 13, 13, 12, 13, 12, 13, 11, 14, 14, 13, 13, 13, 13, 12, 10,
+ 13, 14, 16, 14, 15, 14, 16, 13, 16, 16, 16, 14, 16, 14, 15, 12,
+ 12, 16, 14, 14, 16, 15, 14, 13, 16, 16, 14, 14, 15, 15, 13, 12,
+ 13, 16, 15, 14, 16, 16, 15, 13, 16, 16, 15, 14, 16, 16, 14, 12,
+ 14, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 12,
+ 10, 13, 14, 13, 11, 11, 13, 12, 13, 14, 13, 13, 11, 12, 12, 10,
+ 11, 14, 15, 15, 13, 12, 14, 13, 16, 16, 16, 15, 14, 13, 14, 11,
+ 12, 14, 16, 16, 14, 12, 16, 13, 16, 16, 16, 16, 15, 13, 16, 12,
+ 12, 16, 15, 16, 14, 15, 14, 14, 16, 16, 15, 16, 14, 14, 13, 12,
+ 13, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16, 14, 15, 12,
+ 14, 16, 16, 16, 16, 14, 16, 14, 16, 16, 16, 16, 16, 15, 16, 13,
+ 15, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 15, 13,
+ 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 13,
+ 15, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 13,
+  6, 10, 10, 10, 10, 10, 10, 10,  8, 10,  9,  9,  8,  9,  9,  7,
+  9, 12, 13, 12, 13, 12, 13, 12, 12, 12, 12, 11, 12, 11, 12, 10,
+ 12, 14, 16, 14, 16, 14, 16, 14, 16, 15, 15, 14, 16, 14, 15, 12,
+  8, 12, 11, 11, 12, 12, 12, 11, 11, 12, 10, 10, 11, 12, 10,  9,
+ 10, 13, 13, 12, 14, 13, 14, 12, 13, 13, 12, 11, 13, 13, 12, 10,
+ 13, 15, 16, 14, 16, 16, 16, 14, 16, 15, 15, 13, 16, 15, 15, 12,
+ 11, 15, 13, 13, 15, 15, 15, 14, 14, 14, 11, 12, 14, 14, 12, 11,
+ 13, 16, 14, 14, 16, 16, 16, 14, 16, 15, 13, 13, 16, 14, 14, 11,
+ 14, 16, 16, 14, 16, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 12,
+  8, 12, 12, 12, 11, 11, 12, 12, 11, 12, 11, 11,  9, 10, 10,  9,
+ 10, 13, 14, 13, 13, 12, 14, 13, 13, 13, 13, 13, 12, 11, 12, 10,
+ 13, 15, 16, 15, 16, 14, 16, 14, 16, 16, 16, 15, 16, 13, 15, 12,
+ 10, 14, 13, 13, 13, 13, 13, 13, 13, 14, 12, 12, 12, 12, 11, 10,
+ 10, 13, 13, 13, 13, 13, 14, 12, 13, 14, 13, 12, 13, 12, 12, 10,
+ 13, 16, 16, 14, 16, 15, 16, 14, 16, 16, 15, 14, 16, 14, 15, 11,
+ 13, 16, 15, 16, 16, 16, 15, 14, 16, 16, 14, 14, 15, 15, 13, 12,
+ 13, 16, 15, 14, 16, 16, 16, 14, 16, 16, 14, 14, 15, 15, 14, 11,
+ 14, 16, 16, 15, 16, 16, 16, 14, 16, 16, 16, 15, 16, 16, 15, 12,
+ 11, 14, 15, 14, 13, 13, 14, 14, 13, 15, 14, 14, 11, 12, 12, 11,
+ 13, 16, 16, 16, 14, 14, 16, 14, 16, 16, 16, 15, 14, 13, 14, 12,
+ 14, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13,
+ 13, 16, 16, 16, 15, 16, 15, 15, 16, 16, 15, 16, 14, 14, 13, 12,
+ 13, 16, 16, 15, 15, 14, 16, 14, 16, 16, 16, 15, 14, 14, 14, 11,
+ 14, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 15, 16, 12,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 13,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12,
+  9, 13, 13, 13, 13, 13, 14, 13, 10, 12, 11, 12, 11, 12, 11, 10,
+ 12, 15, 16, 15, 16, 16, 16, 16, 14, 14, 14, 13, 14, 13, 14, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14,
+ 11, 15, 14, 14, 15, 14, 15, 14, 13, 14, 11, 12, 13, 13, 12, 11,
+ 13, 16, 16, 15, 16, 16, 16, 15, 15, 15, 14, 13, 16, 15, 14, 12,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 13,
+ 12, 16, 14, 15, 16, 16, 16, 16, 14, 16, 11, 13, 15, 16, 13, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 16, 15, 12,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 13,
+ 11, 15, 14, 14, 13, 14, 15, 14, 12, 14, 13, 13, 11, 12, 12, 11,
+ 13, 16, 16, 16, 16, 15, 16, 16, 15, 15, 15, 15, 14, 13, 14, 12,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 13,
+ 13, 16, 16, 16, 16, 16, 16, 15, 14, 16, 13, 14, 13, 14, 13, 11,
+ 13, 16, 16, 16, 16, 16, 16, 15, 15, 16, 15, 14, 14, 14, 14, 11,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 15, 16, 16, 13, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 16, 16, 15, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 12,
+ 11, 16, 16, 15, 13, 15, 16, 15, 13, 15, 15, 15, 11, 12, 12, 11,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 15, 12,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 14, 13, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 14, 14, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 12,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 14, 13,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 12,
+ 12, 14, 14, 14, 14, 15, 16, 14, 14, 16, 15, 14, 14, 15, 14, 11,
+], [
+  1,  5,  5,  6,  5,  6,  7,  7,  5,  7,  6,  7,  5,  6,  6,  6,
+  6,  9, 10,  9, 10,  9, 11, 10, 11, 11, 11, 10, 11, 10, 11,  9,
+ 10, 11, 14, 12, 14, 12, 16, 12, 16, 13, 16, 13, 14, 13, 16, 12,
+  6, 10,  9,  9, 10, 11, 11, 10, 10, 11,  9, 10, 10, 11, 10,  9,
+  8, 11, 11, 10, 13, 12, 13, 12, 13, 13, 12, 12, 13, 13, 13, 11,
+ 11, 13, 16, 12, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 13,
+ 10, 14, 11, 12, 14, 14, 13, 13, 13, 16, 12, 13, 14, 16, 13, 12,
+ 11, 14, 13, 12, 16, 16, 16, 14, 16, 16, 14, 14, 16, 16, 16, 13,
+ 12, 14, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+  6, 10, 10, 11,  9,  9, 11, 10, 10, 11, 11, 11,  9, 10, 10,  9,
+  9, 12, 13, 12, 12, 11, 13, 12, 13, 13, 13, 13, 12, 12, 13, 11,
+ 12, 13, 16, 16, 16, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 13,
+  9, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 12, 11,
+ 10, 14, 14, 13, 14, 13, 14, 13, 16, 16, 14, 15, 14, 14, 14, 12,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 10, 14, 14, 16, 11, 12, 14, 13, 14, 16, 16, 16, 12, 13, 13, 12,
+ 12, 16, 16, 16, 13, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 13,
+ 13, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  6, 10, 10, 10, 10, 11, 11, 11,  9, 11,  9, 10,  9, 10, 10,  9,
+  9, 13, 13, 13, 13, 13, 14, 13, 12, 13, 13, 12, 13, 12, 13, 11,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+  8, 13, 12, 12, 13, 13, 13, 13, 11, 13, 10, 12, 12, 13, 12, 11,
+ 10, 14, 13, 13, 16, 16, 16, 14, 14, 14, 13, 13, 14, 14, 14, 12,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 11, 16, 13, 16, 16, 16, 16, 16, 14, 16, 12, 13, 16, 16, 14, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  8, 13, 13, 13, 11, 12, 13, 13, 11, 13, 12, 13, 10, 12, 12, 11,
+ 10, 14, 16, 16, 14, 13, 16, 14, 14, 16, 16, 14, 13, 13, 14, 12,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 10, 16, 14, 16, 14, 14, 14, 14, 13, 16, 13, 14, 13, 14, 12, 12,
+ 10, 14, 14, 14, 14, 16, 16, 14, 14, 16, 14, 14, 14, 14, 14, 12,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 14, 14, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  9, 14, 13, 14, 13, 14, 16, 16, 11, 13, 12, 13, 11, 13, 12, 12,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 14, 16, 16, 16, 16, 16, 13, 16, 12, 13, 14, 16, 13, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 14, 16, 12, 16, 16, 16, 14, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 14, 16, 16, 16, 13, 16, 14, 16, 12, 13, 13, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 12, 16, 14, 14,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13,
+], [
+  1,  5,  5,  6,  5,  6,  7,  8,  5,  7,  6,  8,  6,  7,  7,  7,
+  5,  9, 10, 10, 10, 10, 12, 11, 10, 11, 11, 11, 10, 11, 12, 10,
+  9, 11, 13, 12, 13, 12, 16, 14, 16, 14, 16, 16, 16, 13, 16, 13,
+  5, 10,  9, 10, 10, 11, 11, 11, 10, 11,  9, 11, 10, 11, 11, 10,
+  8, 11, 11, 11, 12, 13, 13, 13, 12, 13, 12, 12, 13, 13, 13, 12,
+ 11, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  9, 14, 11, 12, 14, 16, 13, 14, 13, 16, 12, 14, 16, 16, 13, 13,
+ 11, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 14, 14, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  5, 10, 11, 11,  9, 10, 11, 11, 10, 12, 11, 12,  9, 11, 11, 11,
+  8, 12, 13, 13, 11, 11, 14, 13, 13, 14, 13, 16, 12, 12, 13, 12,
+ 11, 13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  9, 13, 12, 13, 12, 13, 13, 14, 13, 16, 13, 16, 13, 16, 13, 13,
+ 10, 14, 13, 14, 13, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  9, 14, 16, 16, 11, 12, 14, 16, 13, 16, 16, 16, 12, 14, 13, 13,
+ 11, 16, 16, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 14, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  5, 10, 10, 11, 10, 11, 12, 12,  8, 11, 10, 11,  9, 11, 11, 11,
+  9, 12, 13, 13, 13, 13, 16, 16, 12, 13, 13, 13, 13, 13, 16, 13,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  8, 13, 11, 13, 12, 13, 13, 14, 11, 13, 10, 13, 12, 14, 12, 12,
+ 10, 14, 13, 14, 16, 16, 16, 16, 13, 16, 13, 14, 16, 16, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 13, 16, 16, 16, 16, 16, 13, 16, 12, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  8, 13, 13, 13, 11, 13, 14, 16, 11, 13, 13, 14, 10, 12, 12, 12,
+ 10, 14, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 13, 16, 14,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 10, 16, 14, 16, 13, 16, 16, 16, 13, 16, 13, 16, 13, 16, 13, 14,
+ 10, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 13,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 10, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+  9, 14, 13, 16, 13, 16, 16, 16, 10, 14, 12, 14, 11, 13, 13, 13,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 16, 16, 16, 16, 13, 16, 13, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 10, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 11, 16, 16, 16, 14, 16, 16, 16, 14, 16, 16, 16, 12, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 10, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 14,
+]];
+
+const RV34_INTER_CBP: &[[[u8; 16]; 4]; 7] = &[
+[
+ [ 0,  6,  6,  3,  6,  4,  5,  3,  6,  5,  4,  3,  3,  4,  4,  3 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  3,  6,  5,  4,  3,  4,  4,  4,  2 ],
+ [ 0,  7,  7,  4,  7,  5,  5,  4,  7,  5,  5,  4,  5,  4,  4,  1 ],
+ [ 0,  7,  7,  5,  7,  5,  6,  4,  7,  6,  5,  3,  5,  4,  4,  1 ]
+], [
+ [ 0,  6,  6,  3,  6,  3,  5,  4,  6,  5,  3,  4,  3,  4,  4,  3 ],
+ [ 0,  6,  6,  4,  6,  4,  4,  4,  6,  4,  4,  3,  4,  4,  4,  2 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  4,  6,  5,  4,  3,  4,  4,  3,  2 ],
+ [ 0,  7,  7,  5,  7,  5,  6,  4,  7,  6,  5,  3,  5,  4,  4,  1 ]
+], [
+ [ 0,  6,  6,  3,  6,  3,  5,  4,  6,  5,  3,  4,  3,  4,  4,  3 ],
+ [ 0,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4,  4,  4,  4,  4,  2 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  3,  6,  5,  4,  3,  4,  4,  4,  2 ],
+ [ 0,  7,  7,  5,  7,  5,  6,  4,  7,  6,  5,  3,  5,  4,  4,  1 ]
+], [
+ [ 0,  6,  6,  3,  6,  3,  5,  4,  6,  5,  3,  4,  3,  4,  4,  3 ],
+ [ 0,  5,  5,  3,  5,  4,  5,  4,  5,  5,  4,  4,  4,  4,  4,  2 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  3,  6,  5,  4,  3,  4,  4,  4,  2 ],
+ [ 0,  7,  7,  4,  7,  5,  6,  4,  7,  6,  5,  4,  4,  4,  4,  1 ]
+], [
+ [ 0,  5,  5,  3,  5,  3,  5,  4,  5,  5,  3,  4,  3,  4,  4,  4 ],
+ [ 0,  5,  5,  3,  5,  4,  5,  4,  5,  5,  3,  4,  3,  4,  4,  3 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  4,  6,  5,  4,  3,  4,  4,  3,  2 ],
+ [ 0,  7,  7,  4,  7,  5,  6,  4,  7,  6,  5,  4,  4,  4,  4,  1 ]
+], [
+ [ 0,  5,  5,  3,  5,  3,  5,  4,  5,  5,  3,  4,  3,  4,  4,  4 ],
+ [ 0,  5,  5,  3,  5,  4,  5,  4,  5,  5,  3,  4,  3,  4,  4,  3 ],
+ [ 0,  5,  5,  3,  5,  4,  4,  4,  5,  4,  4,  4,  3,  4,  4,  3 ],
+ [ 0,  6,  6,  4,  6,  4,  5,  4,  6,  5,  4,  3,  4,  4,  3,  2 ]
+], [
+ [ 0,  4,  4,  3,  4,  3,  5,  5,  4,  5,  3,  5,  3,  5,  4,  5 ],
+ [ 0,  4,  4,  3,  4,  4,  5,  4,  4,  5,  3,  5,  3,  5,  4,  4 ],
+ [ 0,  4,  4,  3,  4,  4,  5,  4,  4,  5,  4,  4,  3,  4,  4,  4 ],
+ [ 0,  4,  4,  3,  5,  4,  5,  4,  5,  5,  4,  4,  3,  4,  4,  3 ]
+]];
+
+const RV34_INTER_FIRSTPAT: &'static [[[u8; 864]; 2]; 7] = &[
+  [
+    [
+       0,  7,  5,  7,  5,  7,  6,  6,  7, 10,  7,  9,  8,  9,  8,  7,
+      12, 14, 11, 12, 12, 12, 11,  9,  6,  9,  6,  8,  7,  9,  7,  7,
+       8, 11,  8,  9,  9, 10,  9,  8, 13, 15, 12, 12, 12, 13, 11,  9,
+      10, 13,  9, 10, 11, 12,  9,  8, 12, 14, 10, 11, 12, 13, 10,  9,
+      16, 16, 12, 12, 14, 13, 11,  9,  6,  9,  7,  9,  7,  9,  8,  7,
+       9, 11,  9, 10,  9, 10,  9,  8, 14, 16, 12, 12, 13, 13, 11,  9,
+       8, 11,  8, 10,  9, 10,  9,  8, 10, 13, 10, 11, 10, 11,  9,  8,
+      14, 16, 12, 12, 13, 13, 11,  9, 12, 14, 10, 11, 12, 13, 10,  9,
+      13, 16, 11, 12, 13, 13, 10,  9, 16, 16, 13, 12, 14, 14, 11,  9,
+      11, 13, 11, 12, 10, 11, 10,  9, 13, 14, 12, 12, 11, 12, 10,  9,
+      16, 16, 13, 13, 13, 13, 11,  9, 12, 15, 12, 12, 11, 12, 10,  9,
+      13, 16, 13, 13, 12, 12, 11,  9, 16, 16, 14, 13, 13, 13, 11,  9,
+      14, 16, 13, 13, 13, 14, 11,  9, 16, 16, 13, 13, 14, 14, 11,  9,
+      16, 16, 13, 13, 14, 13, 11,  8,  4,  9,  6,  8,  6,  9,  7,  7,
+       8, 11,  8,  9,  9, 10,  8,  8, 13, 15, 12, 12, 13, 13, 11,  9,
+       7, 10,  7,  9,  8, 10,  8,  8,  9, 12,  9, 10, 10, 11,  9,  8,
+      14, 16, 12, 12, 13, 13, 11,  9, 11, 13,  9, 10, 11, 12,  9,  8,
+      12, 14, 10, 11, 12, 13, 10,  9, 16, 16, 13, 12, 14, 14, 11,  9,
+       7, 10,  8,  9,  8, 10,  8,  8, 10, 12, 10, 11, 10, 11,  9,  8,
+      14, 16, 13, 13, 13, 13, 11,  9,  9, 12,  9, 10,  9, 11,  9,  8,
+      11, 13, 10, 11, 10, 11, 10,  9, 15, 16, 13, 13, 13, 13, 11,  9,
+      12, 14, 11, 11, 12, 13, 10,  9, 13, 16, 11, 12, 13, 13, 10,  9,
+      16, 16, 12, 12, 14, 13, 11,  8, 11, 14, 11, 12, 10, 11, 10,  9,
+      13, 15, 12, 13, 11, 12, 10,  9, 16, 16, 14, 13, 13, 13, 11,  9,
+      12, 15, 12, 13, 11, 12, 10,  9, 13, 16, 13, 13, 12, 12, 11,  9,
+      16, 16, 14, 13, 13, 13, 11,  9, 15, 16, 13, 13, 13, 13, 11,  9,
+      16, 16, 13, 13, 13, 13, 11,  9, 16, 16, 13, 12, 13, 13, 10,  7,
+       8, 11,  8, 10,  9, 11,  9,  9, 10, 13, 10, 11, 11, 12, 10,  9,
+      15, 16, 13, 13, 14, 14, 12, 10,  9, 12,  9, 11, 10, 11,  9,  9,
+      12, 14, 11, 11, 11, 12, 10,  9, 16, 16, 13, 13, 14, 14, 12, 10,
+      12, 14, 10, 11, 12, 13, 10,  9, 14, 16, 11, 12, 13, 14, 10,  9,
+      16, 16, 13, 13, 15, 14, 11,  9,  9, 12, 10, 11,  9, 11, 10,  9,
+      12, 14, 11, 12, 11, 12, 10,  9, 16, 16, 14, 13, 14, 14, 12, 10,
+      11, 14, 10, 12, 11, 12, 10,  9, 12, 15, 11, 12, 12, 13, 11, 10,
+      16, 16, 14, 13, 14, 14, 12, 10, 13, 16, 11, 12, 13, 14, 11,  9,
+      14, 16, 12, 12, 13, 14, 11,  9, 16, 16, 13, 13, 14, 14, 11,  9,
+      12, 15, 12, 13, 10, 12, 10,  9, 14, 16, 13, 13, 11, 12, 11, 10,
+      16, 16, 14, 14, 14, 13, 12,  9, 13, 16, 13, 13, 12, 13, 11, 10,
+      14, 16, 13, 13, 12, 13, 11, 10, 16, 16, 14, 14, 13, 13, 12,  9,
+      15, 16, 13, 13, 13, 14, 11,  9, 16, 16, 13, 13, 13, 14, 11,  9,
+      16, 16, 13, 12, 13, 13, 10,  8, 10, 13, 10, 11, 10, 12, 10,  9,
+      12, 14, 11, 12, 12, 13, 11, 10, 16, 16, 13, 13, 14, 14, 12,  9,
+      11, 14, 10, 11, 11, 12, 10,  9, 13, 16, 11, 12, 12, 13, 11, 10,
+      16, 16, 14, 13, 14, 14, 12,  9, 12, 15, 10, 11, 12, 13,  9,  8,
+      14, 16, 11, 11, 13, 14, 10,  8, 16, 16, 12, 12, 14, 14, 10,  8,
+      11, 14, 11, 12, 11, 12, 10,  9, 13, 16, 12, 13, 12, 13, 11, 10,
+      16, 16, 14, 13, 14, 14, 12,  9, 12, 15, 11, 12, 11, 13, 10, 10,
+      13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 14, 13, 14, 14, 12,  9,
+      13, 16, 11, 11, 13, 13, 10,  8, 14, 16, 11, 12, 13, 14, 10,  8,
+      16, 16, 12, 12, 14, 14, 10,  8, 12, 15, 12, 13, 10, 11, 10,  9,
+      14, 16, 13, 13, 11, 12, 10,  9, 16, 16, 14, 13, 13, 13, 11,  8,
+      13, 16, 12, 13, 11, 12, 10,  9, 14, 16, 13, 13, 12, 12, 10,  9,
+      16, 16, 14, 13, 13, 12, 10,  8, 14, 16, 12, 12, 12, 13, 10,  8,
+      14, 16, 12, 12, 12, 13, 10,  7, 16, 16, 11, 11, 12, 11,  8,  5,
+    ], [
+       0,  7,  4,  8,  5,  8,  7,  8,  6, 10,  7, 10,  8, 10,  9,  9,
+      13, 16, 12, 13, 13, 14, 12, 12,  4, 10,  6,  9,  8, 11,  8,  9,
+       8, 12,  8, 11, 10, 12, 10, 10, 14, 16, 12, 13, 14, 15, 12, 12,
+       9, 14,  9, 11, 12, 14, 11, 11, 11, 15, 10, 12, 13, 14, 11, 11,
+      15, 16, 13, 14, 15, 16, 13, 12,  5, 10,  7, 10,  7, 10,  9,  9,
+       8, 12,  9, 11, 10, 11, 10, 10, 14, 16, 13, 14, 14, 14, 12, 12,
+       8, 12,  8, 11, 10, 12, 10, 10, 10, 14, 10, 12, 11, 13, 10, 11,
+      15, 16, 13, 14, 14, 15, 13, 12, 11, 16, 10, 12, 13, 15, 11, 11,
+      13, 16, 11, 13, 14, 15, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12,
+      11, 15, 11, 13, 11, 13, 11, 11, 13, 16, 12, 14, 12, 13, 12, 12,
+      16, 16, 14, 15, 15, 15, 13, 12, 12, 16, 12, 14, 12, 14, 12, 12,
+      14, 16, 13, 14, 13, 14, 12, 12, 16, 16, 14, 16, 16, 16, 13, 12,
+      14, 16, 13, 14, 15, 16, 13, 12, 16, 16, 14, 15, 16, 16, 13, 12,
+      16, 16, 15, 16, 16, 16, 13, 12,  2,  9,  5,  8,  6,  9,  8,  9,
+       7, 11,  8, 10,  9, 11,  9, 10, 13, 16, 12, 13, 14, 14, 12, 12,
+       5, 11,  6, 10,  9, 11,  9,  9,  9, 13,  9, 11, 10, 12, 10, 10,
+      14, 16, 12, 14, 14, 15, 12, 12,  9, 14,  9, 11, 12, 14, 10, 11,
+      11, 16, 10, 12, 13, 14, 11, 11, 16, 16, 13, 14, 15, 16, 13, 12,
+       6, 11,  7, 10,  8, 11,  9,  9,  9, 13,  9, 11, 10, 12, 10, 10,
+      14, 16, 13, 14, 14, 14, 12, 12,  8, 13,  8, 11, 10, 12, 10, 10,
+      10, 13, 10, 12, 11, 13, 10, 11, 14, 16, 13, 14, 14, 15, 12, 12,
+      11, 15, 10, 12, 13, 15, 11, 11, 12, 16, 11, 13, 13, 15, 12, 11,
+      16, 16, 13, 14, 15, 16, 13, 12, 11, 15, 11, 13, 10, 13, 11, 11,
+      13, 16, 12, 14, 12, 13, 12, 11, 16, 16, 14, 15, 15, 15, 13, 12,
+      12, 16, 12, 13, 12, 14, 12, 12, 13, 16, 12, 14, 13, 14, 12, 12,
+      16, 16, 14, 15, 15, 15, 13, 12, 14, 16, 13, 14, 15, 16, 12, 12,
+      16, 16, 13, 14, 15, 16, 12, 12, 16, 16, 14, 15, 16, 16, 13, 12,
+       6, 12,  7, 10,  9, 12,  9, 10,  9, 13,  9, 12, 11, 13, 11, 11,
+      14, 16, 13, 14, 15, 15, 13, 12,  8, 13,  8, 11, 10, 13, 10, 10,
+      10, 14, 10, 12, 12, 14, 11, 11, 15, 16, 13, 14, 16, 16, 13, 12,
+      10, 15,  9, 12, 12, 15, 11, 11, 12, 16, 11, 13, 14, 16, 12, 12,
+      16, 16, 14, 14, 16, 16, 13, 12,  8, 13,  9, 11, 10, 12, 10, 11,
+      11, 14, 11, 12, 11, 13, 11, 11, 16, 16, 14, 15, 15, 16, 13, 12,
+      10, 14, 10, 12, 11, 13, 11, 11, 11, 15, 11, 13, 12, 14, 11, 11,
+      15, 16, 13, 14, 15, 16, 13, 12, 12, 16, 11, 13, 13, 16, 12, 12,
+      13, 16, 11, 13, 14, 16, 12, 12, 16, 16, 13, 14, 16, 16, 13, 12,
+      12, 16, 12, 14, 11, 13, 11, 11, 13, 16, 13, 14, 12, 14, 12, 12,
+      16, 16, 15, 16, 16, 16, 14, 13, 13, 16, 12, 14, 12, 14, 12, 12,
+      14, 16, 13, 14, 13, 14, 12, 12, 16, 16, 14, 16, 14, 16, 13, 12,
+      15, 16, 13, 15, 15, 16, 13, 12, 15, 16, 13, 15, 14, 16, 13, 12,
+      16, 16, 14, 15, 15, 16, 13, 11,  8, 13,  8, 11, 10, 13, 10, 11,
+      11, 15, 10, 12, 12, 14, 11, 11, 15, 16, 13, 14, 15, 15, 13, 12,
+       9, 14,  9, 12, 11, 14, 10, 11, 11, 16, 10, 12, 13, 14, 11, 11,
+      16, 16, 13, 14, 15, 16, 13, 12, 11, 15,  9, 12, 12, 14, 10, 10,
+      12, 16, 11, 12, 14, 15, 11, 11, 16, 16, 13, 14, 16, 16, 12, 11,
+       9, 14, 10, 12, 11, 13, 11, 11, 12, 16, 11, 13, 12, 14, 11, 11,
+      16, 16, 14, 14, 15, 15, 13, 12, 10, 15, 10, 12, 12, 14, 11, 11,
+      12, 16, 11, 13, 13, 14, 11, 11, 16, 16, 14, 14, 15, 16, 13, 12,
+      12, 16, 10, 12, 13, 15, 11, 11, 13, 16, 11, 13, 14, 15, 11, 11,
+      16, 16, 13, 13, 15, 16, 12, 11, 12, 16, 11, 13, 10, 13, 11, 11,
+      14, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 14, 15, 13, 11,
+      13, 16, 12, 14, 12, 14, 11, 11, 13, 16, 12, 14, 12, 14, 11, 11,
+      16, 16, 14, 15, 14, 14, 12, 11, 14, 16, 12, 13, 13, 15, 11, 11,
+      14, 16, 12, 13, 13, 14, 11, 11, 15, 16, 12, 13, 13, 13, 10,  9,
+    ],
+  ], [
+    [
+       0,  7,  4,  7,  5,  7,  6,  6,  6, 10,  7,  8,  8,  9,  8,  7,
+      13, 14, 11, 12, 12, 12, 11,  9,  5,  9,  6,  8,  7,  9,  7,  7,
+       8, 11,  8,  9,  9, 10,  9,  8, 13, 16, 12, 12, 12, 13, 11,  9,
+      10, 13,  8, 10, 11, 12,  9,  9, 12, 14, 10, 11, 12, 13, 10,  9,
+      15, 16, 12, 12, 14, 14, 11,  9,  6, 10,  7,  9,  7,  9,  8,  7,
+       8, 11,  9, 10,  9, 10,  9,  8, 14, 16, 12, 12, 13, 12, 11,  9,
+       8, 11,  8, 10,  9, 10,  9,  8, 10, 13, 10, 11, 10, 11,  9,  9,
+      14, 16, 12, 12, 13, 13, 11,  9, 12, 15, 10, 11, 12, 13, 10,  9,
+      13, 16, 11, 12, 13, 13, 10,  9, 16, 16, 12, 13, 14, 14, 11,  9,
+      10, 14, 11, 12,  9, 11, 10,  9, 12, 15, 12, 13, 11, 12, 11,  9,
+      16, 16, 13, 13, 13, 13, 11,  9, 12, 15, 12, 13, 11, 12, 11,  9,
+      13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 13, 13, 13, 11,  9,
+      14, 16, 13, 13, 13, 14, 11, 10, 16, 16, 13, 13, 13, 14, 11, 10,
+      16, 16, 13, 13, 14, 14, 11,  9,  4,  9,  6,  8,  6,  9,  7,  7,
+       8, 11,  8,  9,  9, 10,  9,  8, 13, 15, 12, 12, 13, 13, 11,  9,
+       6, 10,  7,  9,  8, 10,  8,  8,  9, 12,  9, 10, 10, 11,  9,  8,
+      14, 16, 12, 12, 13, 13, 11, 10, 10, 13,  8, 10, 11, 12,  9,  9,
+      12, 15, 10, 11, 12, 13, 10,  9, 16, 16, 12, 12, 14, 14, 11,  9,
+       7, 11,  8,  9,  7, 10,  8,  8,  9, 12, 10, 11,  9, 11,  9,  9,
+      14, 16, 12, 13, 13, 13, 11, 10,  9, 12,  9, 10,  9, 11,  9,  9,
+      10, 13, 10, 11, 10, 11, 10,  9, 14, 16, 12, 13, 13, 13, 11,  9,
+      12, 15, 10, 11, 12, 13, 10,  9, 13, 16, 11, 12, 13, 13, 10,  9,
+      16, 16, 12, 12, 14, 14, 11,  9, 10, 14, 11, 12,  9, 11, 10,  9,
+      12, 16, 12, 13, 11, 12, 11,  9, 16, 16, 14, 14, 13, 13, 11,  9,
+      12, 16, 12, 13, 11, 12, 10, 10, 13, 16, 12, 13, 11, 12, 11, 10,
+      16, 16, 13, 13, 13, 13, 11,  9, 14, 16, 13, 13, 13, 14, 11,  9,
+      15, 16, 13, 13, 13, 14, 11,  9, 16, 16, 13, 13, 13, 13, 10,  8,
+       7, 11,  8, 10,  9, 11,  9,  9, 10, 13, 10, 11, 11, 12, 10, 10,
+      15, 16, 13, 13, 14, 14, 12, 10,  9, 13,  9, 11, 10, 12, 10,  9,
+      11, 14, 10, 12, 12, 13, 10, 10, 16, 16, 13, 13, 14, 14, 12, 10,
+      11, 15,  9, 11, 12, 13, 10,  9, 13, 16, 11, 12, 13, 14, 11, 10,
+      16, 16, 13, 13, 15, 15, 11, 10,  9, 13, 10, 11,  9, 11, 10,  9,
+      11, 14, 11, 12, 11, 12, 11, 10, 16, 16, 14, 14, 14, 14, 12, 10,
+      10, 14, 10, 12, 11, 12, 10, 10, 12, 15, 11, 12, 12, 13, 11, 10,
+      16, 16, 13, 13, 14, 14, 12, 10, 13, 16, 11, 12, 13, 14, 11, 10,
+      13, 16, 11, 12, 13, 14, 11, 10, 16, 16, 12, 13, 14, 14, 11,  9,
+      11, 15, 12, 13, 10, 12, 10, 10, 13, 16, 13, 14, 11, 13, 11, 10,
+      16, 16, 14, 14, 14, 14, 12, 10, 13, 16, 13, 13, 11, 13, 11, 10,
+      14, 16, 13, 14, 12, 13, 11, 10, 16, 16, 14, 14, 13, 13, 12, 10,
+      15, 16, 13, 14, 14, 14, 11, 10, 15, 16, 13, 13, 13, 14, 11, 10,
+      16, 16, 12, 13, 13, 13, 10,  8,  9, 13, 10, 11, 10, 12, 10, 10,
+      12, 15, 11, 12, 12, 13, 11, 10, 16, 16, 14, 13, 14, 14, 12, 10,
+      10, 14, 10, 12, 11, 13, 10, 10, 13, 16, 11, 12, 12, 14, 11, 10,
+      16, 16, 13, 13, 14, 14, 12, 10, 12, 16,  9, 11, 12, 14, 10,  9,
+      13, 16, 10, 12, 13, 14, 10,  9, 16, 16, 12, 12, 14, 14, 11,  9,
+      10, 14, 11, 12, 10, 12, 10, 10, 13, 16, 12, 13, 12, 13, 11, 10,
+      16, 16, 14, 14, 14, 14, 12, 10, 11, 16, 11, 12, 11, 13, 11, 10,
+      13, 16, 12, 13, 12, 14, 11, 10, 16, 16, 14, 14, 14, 14, 12, 10,
+      13, 16, 11, 12, 13, 14, 10,  9, 14, 16, 11, 12, 13, 14, 10,  9,
+      16, 16, 12, 12, 14, 14, 10,  8, 12, 16, 12, 13, 10, 12, 10,  9,
+      14, 16, 13, 13, 11, 12, 11,  9, 16, 16, 14, 14, 13, 13, 11,  9,
+      13, 16, 12, 13, 11, 12, 10,  9, 14, 16, 13, 13, 11, 13, 11,  9,
+      16, 16, 14, 14, 13, 13, 11,  9, 14, 16, 12, 13, 12, 13, 10,  8,
+      14, 16, 12, 12, 12, 13, 10,  8, 15, 16, 11, 11, 11, 12,  9,  6,
+    ], [
+       0,  7,  4,  7,  5,  8,  7,  8,  5, 10,  7, 10,  8, 10,  9, 10,
+      13, 16, 12, 14, 14, 14, 13, 12,  4, 10,  6,  9,  8, 11,  9,  9,
+       8, 12,  8, 11, 10, 12, 10, 10, 14, 16, 13, 14, 14, 15, 13, 12,
+       9, 14,  9, 12, 12, 14, 11, 11, 12, 16, 11, 13, 13, 15, 12, 12,
+      15, 16, 14, 15, 15, 16, 13, 13,  5, 10,  7, 10,  7, 10,  9,  9,
+       8, 12,  9, 11,  9, 11, 10, 10, 14, 16, 13, 14, 14, 15, 13, 12,
+       7, 12,  8, 11, 10, 12, 10, 10, 10, 13, 10, 12, 11, 13, 11, 11,
+      15, 16, 13, 15, 14, 16, 13, 13, 11, 16, 11, 13, 13, 16, 12, 12,
+      13, 16, 12, 14, 14, 16, 12, 12, 16, 16, 14, 16, 16, 16, 14, 13,
+      11, 15, 12, 14, 11, 13, 11, 12, 13, 16, 12, 14, 12, 14, 12, 12,
+      16, 16, 14, 16, 14, 16, 13, 13, 13, 16, 12, 14, 12, 14, 12, 12,
+      14, 16, 13, 15, 13, 15, 13, 13, 16, 16, 15, 16, 16, 16, 14, 13,
+      15, 16, 13, 16, 15, 16, 13, 13, 16, 16, 14, 16, 16, 16, 14, 13,
+      16, 16, 16, 16, 16, 16, 14, 13,  2,  9,  5,  8,  6,  9,  8,  9,
+       7, 11,  8, 10,  9, 11,  9, 10, 14, 16, 13, 14, 14, 15, 13, 12,
+       5, 11,  6, 10,  9, 11,  9, 10,  8, 13,  9, 11, 11, 12, 10, 11,
+      14, 16, 13, 14, 14, 16, 13, 13,  9, 15,  9, 12, 12, 14, 11, 11,
+      12, 16, 11, 13, 13, 15, 12, 12, 16, 16, 14, 15, 16, 16, 14, 13,
+       6, 11,  7, 10,  8, 11,  9, 10,  9, 13,  9, 12, 10, 12, 10, 11,
+      14, 16, 13, 14, 14, 15, 13, 13,  8, 12,  8, 11, 10, 12, 10, 11,
+       9, 13, 10, 12, 11, 13, 11, 11, 14, 16, 13, 14, 14, 16, 13, 13,
+      12, 16, 11, 13, 13, 15, 12, 12, 13, 16, 11, 13, 14, 16, 12, 12,
+      16, 16, 14, 15, 16, 16, 13, 13, 11, 15, 11, 14, 10, 13, 11, 12,
+      13, 16, 13, 15, 12, 14, 12, 12, 16, 16, 15, 16, 15, 16, 14, 13,
+      12, 16, 12, 14, 12, 14, 12, 12, 13, 16, 13, 15, 13, 14, 12, 13,
+      16, 16, 15, 16, 15, 16, 13, 13, 15, 16, 13, 16, 15, 16, 13, 13,
+      16, 16, 14, 16, 16, 16, 13, 13, 16, 16, 15, 16, 16, 16, 14, 13,
+       5, 12,  7, 10,  9, 12, 10, 10,  9, 13,  9, 12, 11, 13, 11, 11,
+      15, 16, 13, 14, 15, 15, 13, 13,  7, 13,  8, 11, 10, 13, 10, 11,
+      10, 14, 10, 12, 12, 14, 11, 12, 16, 16, 14, 15, 16, 16, 14, 13,
+      10, 16,  9, 12, 13, 15, 11, 12, 13, 16, 11, 13, 14, 16, 12, 12,
+      16, 16, 14, 16, 16, 16, 14, 13,  8, 13,  9, 12,  9, 12, 10, 11,
+      11, 15, 11, 13, 11, 13, 11, 12, 16, 16, 14, 16, 16, 16, 14, 13,
+       9, 14, 10, 12, 11, 13, 11, 12, 11, 15, 11, 13, 12, 14, 12, 12,
+      16, 16, 14, 16, 15, 16, 14, 13, 12, 16, 11, 14, 14, 16, 12, 12,
+      13, 16, 12, 14, 14, 16, 13, 13, 16, 16, 13, 15, 16, 16, 14, 13,
+      11, 16, 12, 14, 10, 13, 12, 12, 13, 16, 13, 15, 12, 14, 12, 13,
+      16, 16, 16, 16, 16, 16, 14, 14, 13, 16, 13, 15, 12, 15, 12, 13,
+      13, 16, 13, 15, 12, 15, 13, 13, 16, 16, 15, 16, 14, 16, 14, 13,
+      16, 16, 14, 16, 16, 16, 14, 13, 15, 16, 14, 16, 15, 16, 14, 13,
+      16, 16, 14, 16, 15, 16, 13, 12,  8, 14,  9, 12, 10, 14, 11, 12,
+      11, 16, 10, 13, 12, 14, 12, 12, 16, 16, 14, 15, 15, 16, 14, 13,
+       9, 15,  9, 12, 12, 14, 11, 12, 12, 16, 11, 13, 13, 15, 12, 12,
+      16, 16, 14, 15, 16, 16, 14, 13, 11, 16,  9, 12, 13, 15, 11, 11,
+      13, 16, 11, 13, 14, 16, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12,
+       9, 15, 10, 13, 11, 14, 11, 12, 12, 16, 11, 14, 12, 14, 12, 12,
+      16, 16, 14, 16, 16, 16, 14, 13, 10, 16, 10, 13, 12, 15, 12, 12,
+      12, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 16, 16, 16, 14, 13,
+      12, 16, 11, 13, 13, 16, 12, 12, 13, 16, 11, 13, 14, 16, 12, 12,
+      16, 16, 13, 14, 16, 16, 13, 12, 11, 16, 12, 14, 10, 13, 11, 12,
+      13, 16, 13, 15, 12, 14, 12, 12, 16, 16, 16, 16, 15, 16, 13, 12,
+      12, 16, 12, 15, 12, 14, 12, 12, 13, 16, 13, 15, 12, 14, 12, 12,
+      16, 16, 15, 16, 14, 15, 13, 12, 14, 16, 13, 14, 13, 16, 12, 12,
+      13, 16, 12, 14, 13, 15, 12, 12, 14, 16, 12, 13, 13, 14, 11, 10,
+    ],
+  ], [
+    [
+       0,  7,  4,  7,  5,  7,  6,  6,  6, 10,  7,  8,  8,  9,  8,  8,
+      13, 14, 11, 12, 12, 12, 11, 10,  5,  9,  6,  8,  7,  9,  7,  7,
+       8, 11,  8,  9,  9, 10,  9,  8, 13, 16, 12, 12, 13, 13, 11, 10,
+      10, 14,  8, 10, 11, 13,  9,  9, 12, 15, 10, 11, 12, 13, 10, 10,
+      16, 16, 12, 13, 14, 14, 11, 10,  5, 10,  7,  9,  6,  9,  8,  8,
+       8, 11,  9, 10,  9, 10,  9,  8, 14, 16, 12, 12, 13, 13, 11, 10,
+       8, 12,  8, 10,  9, 10,  9,  9, 10, 13,  9, 11, 10, 11,  9,  9,
+      14, 16, 12, 13, 13, 13, 11, 10, 12, 16, 10, 12, 12, 13, 10, 10,
+      13, 16, 11, 12, 13, 14, 11, 10, 16, 16, 12, 13, 14, 14, 11, 10,
+      10, 14, 11, 13,  9, 11, 10, 10, 12, 16, 12, 13, 11, 12, 11, 10,
+      16, 16, 13, 14, 13, 13, 12, 10, 12, 16, 12, 13, 11, 13, 11, 10,
+      13, 16, 12, 13, 12, 13, 11, 10, 16, 16, 13, 14, 13, 14, 12, 10,
+      14, 16, 13, 14, 13, 14, 12, 11, 16, 16, 13, 14, 14, 15, 12, 11,
+      16, 16, 13, 14, 14, 14, 11, 10,  3,  9,  5,  8,  6,  9,  7,  7,
+       8, 11,  8, 10,  9, 10,  9,  8, 14, 15, 12, 12, 13, 13, 11, 10,
+       6, 11,  6,  9,  8, 10,  8,  8,  9, 12,  9, 10, 10, 11,  9,  9,
+      14, 16, 12, 13, 13, 13, 11, 10, 10, 14,  8, 11, 12, 13,  9,  9,
+      12, 16, 10, 11, 12, 13, 10, 10, 16, 16, 12, 13, 14, 14, 11, 10,
+       6, 11,  8, 10,  7, 10,  8,  8,  9, 12, 10, 11,  9, 11,  9,  9,
+      14, 16, 12, 13, 13, 13, 12, 10,  9, 12,  9, 11,  9, 11,  9,  9,
+      10, 13, 10, 11, 10, 12, 10,  9, 14, 16, 12, 13, 13, 13, 11, 10,
+      12, 16, 10, 12, 12, 14, 10, 10, 13, 16, 10, 12, 13, 14, 11, 10,
+      16, 16, 12, 13, 14, 14, 11, 10, 10, 15, 11, 13,  9, 11, 10, 10,
+      12, 16, 12, 13, 11, 12, 11, 10, 16, 16, 14, 14, 13, 14, 12, 10,
+      12, 16, 12, 13, 11, 13, 11, 10, 13, 16, 12, 13, 11, 13, 11, 10,
+      16, 16, 13, 14, 13, 13, 12, 10, 14, 16, 13, 14, 14, 14, 11, 11,
+      15, 16, 13, 14, 13, 14, 11, 10, 16, 16, 13, 13, 13, 14, 11,  9,
+       7, 12,  8, 11,  9, 11,  9, 10, 10, 14, 10, 12, 11, 12, 11, 10,
+      16, 16, 13, 13, 14, 14, 12, 11,  9, 13,  9, 11, 10, 12, 10, 10,
+      11, 15, 10, 12, 12, 13, 11, 10, 16, 16, 13, 14, 14, 14, 12, 11,
+      11, 16,  9, 11, 12, 14, 10, 10, 13, 16, 10, 12, 13, 14, 11, 10,
+      16, 16, 13, 14, 16, 16, 12, 11,  9, 13, 10, 12,  9, 12, 10, 10,
+      11, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 14, 14, 14, 13, 11,
+      10, 14, 10, 12, 11, 13, 11, 10, 12, 16, 11, 13, 12, 13, 11, 11,
+      16, 16, 13, 14, 14, 14, 12, 11, 13, 16, 11, 13, 13, 14, 11, 11,
+      13, 16, 11, 13, 13, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 10,
+      11, 16, 12, 14, 10, 12, 11, 10, 13, 16, 13, 14, 11, 13, 11, 11,
+      16, 16, 15, 16, 14, 14, 13, 11, 13, 16, 13, 14, 12, 13, 11, 11,
+      13, 16, 13, 14, 12, 13, 11, 11, 16, 16, 14, 14, 13, 14, 12, 11,
+      15, 16, 13, 14, 14, 16, 12, 11, 14, 16, 13, 14, 13, 14, 12, 11,
+      16, 16, 12, 13, 13, 14, 11,  9,  9, 14, 10, 12, 10, 13, 11, 11,
+      12, 16, 12, 13, 12, 14, 12, 11, 16, 16, 14, 14, 14, 14, 13, 11,
+      10, 16, 10, 13, 12, 14, 11, 11, 13, 16, 12, 13, 13, 14, 12, 11,
+      16, 16, 14, 14, 15, 15, 13, 11, 12, 16,  9, 12, 13, 14, 10, 10,
+      14, 16, 11, 12, 13, 15, 11, 10, 16, 16, 13, 13, 15, 16, 11, 10,
+      10, 16, 11, 13, 11, 13, 11, 11, 13, 16, 12, 14, 12, 14, 12, 11,
+      16, 16, 14, 14, 14, 14, 13, 11, 11, 16, 11, 13, 12, 14, 11, 11,
+      13, 16, 12, 14, 13, 14, 12, 11, 16, 16, 14, 14, 14, 15, 13, 11,
+      13, 16, 11, 13, 13, 14, 11, 10, 14, 16, 11, 13, 13, 14, 11, 10,
+      16, 16, 12, 13, 14, 15, 11,  9, 12, 16, 12, 14, 10, 13, 11, 10,
+      14, 16, 13, 14, 11, 13, 11, 10, 16, 16, 14, 15, 13, 14, 12, 10,
+      13, 16, 13, 14, 11, 13, 11, 10, 14, 16, 13, 14, 12, 13, 11, 10,
+      16, 16, 14, 14, 13, 13, 11, 10, 14, 16, 12, 13, 13, 14, 11,  9,
+      14, 16, 12, 13, 12, 13, 10,  9, 14, 16, 11, 11, 12, 12,  9,  7,
+    ], [
+       0,  7,  3,  8,  5,  8,  7,  9,  5, 10,  7, 10,  8, 11, 10, 10,
+      14, 16, 14, 15, 14, 16, 14, 14,  4, 10,  6, 10,  8, 11,  9, 10,
+       8, 12,  9, 11, 10, 12, 11, 11, 15, 16, 14, 16, 15, 16, 14, 14,
+      10, 16, 10, 13, 13, 16, 12, 13, 13, 16, 12, 14, 14, 16, 13, 13,
+      16, 16, 16, 16, 16, 16, 14, 15,  4, 10,  7, 10,  7, 10,  9, 10,
+       8, 12,  9, 12, 10, 12, 11, 12, 14, 16, 14, 16, 15, 16, 14, 14,
+       8, 12,  9, 12, 10, 13, 11, 12, 10, 14, 11, 13, 11, 14, 12, 13,
+      16, 16, 14, 16, 16, 16, 14, 15, 12, 16, 12, 14, 14, 16, 13, 14,
+      14, 16, 13, 16, 16, 16, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 12, 16, 11, 14, 13, 13, 13, 16, 13, 16, 13, 15, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 16, 13, 16, 13, 16, 13, 16, 13, 14,
+      14, 16, 14, 16, 14, 16, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  2,  9,  5,  9,  6, 10,  8, 10,
+       7, 11,  8, 11,  9, 12, 10, 11, 14, 16, 14, 16, 15, 16, 14, 14,
+       5, 11,  6, 10,  9, 12, 10, 11,  9, 13,  9, 12, 11, 13, 11, 12,
+      16, 16, 14, 16, 16, 16, 14, 14, 10, 16,  9, 13, 13, 16, 12, 13,
+      13, 16, 12, 14, 14, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 14,
+       5, 11,  8, 11,  7, 11, 10, 11,  9, 13, 10, 13, 10, 13, 11, 12,
+      16, 16, 14, 16, 16, 16, 14, 14,  8, 13,  9, 12, 10, 13, 11, 12,
+      10, 14, 10, 13, 11, 14, 12, 12, 16, 16, 14, 16, 15, 16, 14, 14,
+      12, 16, 12, 14, 14, 16, 13, 14, 14, 16, 12, 16, 15, 16, 13, 14,
+      16, 16, 15, 16, 16, 16, 15, 15, 11, 16, 12, 16, 10, 14, 12, 13,
+      13, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 15, 16,
+      13, 16, 13, 16, 13, 16, 13, 14, 14, 16, 14, 16, 13, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 16, 16, 16, 15, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16,
+       5, 13,  7, 12,  9, 13, 11, 12, 10, 14, 10, 13, 11, 13, 12, 13,
+      16, 16, 16, 16, 16, 16, 16, 15,  7, 14,  8, 12, 11, 14, 11, 12,
+      11, 16, 11, 13, 13, 16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 10, 14, 14, 16, 12, 13, 13, 16, 12, 15, 16, 16, 14, 14,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 14, 10, 13,  9, 13, 11, 12,
+      11, 16, 12, 14, 12, 14, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 11, 14, 12, 14, 12, 13, 11, 16, 12, 14, 12, 15, 13, 13,
+      16, 16, 15, 16, 16, 16, 15, 16, 13, 16, 12, 16, 15, 16, 14, 14,
+      13, 16, 12, 16, 16, 16, 14, 14, 16, 16, 14, 16, 16, 16, 14, 16,
+      11, 16, 13, 16, 10, 14, 12, 13, 14, 16, 14, 16, 13, 16, 14, 14,
+      16, 16, 16, 16, 16, 16, 16, 16, 13, 16, 14, 16, 13, 16, 14, 15,
+      13, 16, 14, 16, 13, 16, 14, 15, 16, 16, 16, 16, 15, 16, 15, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 15, 16,
+      16, 16, 15, 16, 16, 16, 14, 14,  8, 16, 10, 14, 11, 16, 12, 13,
+      12, 16, 12, 14, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 14,
+      10, 16, 10, 14, 12, 16, 12, 13, 13, 16, 12, 15, 14, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 16, 15, 11, 16, 10, 13, 13, 16, 12, 13,
+      14, 16, 12, 14, 15, 16, 13, 13, 16, 16, 16, 16, 16, 16, 15, 14,
+      10, 16, 11, 14, 11, 16, 12, 13, 13, 16, 13, 16, 13, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 16, 15, 11, 16, 12, 14, 13, 16, 13, 14,
+      13, 16, 13, 16, 14, 16, 13, 14, 16, 16, 16, 16, 16, 16, 16, 15,
+      13, 16, 12, 14, 14, 16, 13, 13, 13, 16, 12, 15, 14, 16, 13, 13,
+      16, 16, 14, 16, 16, 16, 14, 13, 11, 16, 12, 16, 11, 15, 12, 13,
+      14, 16, 14, 16, 13, 16, 13, 14, 16, 16, 16, 16, 16, 16, 14, 14,
+      12, 16, 13, 16, 12, 16, 13, 14, 13, 16, 14, 16, 13, 16, 13, 14,
+      16, 16, 16, 16, 14, 16, 14, 14, 14, 16, 13, 16, 14, 16, 13, 13,
+      13, 16, 13, 16, 14, 16, 13, 13, 15, 16, 13, 14, 13, 15, 12, 12,
+    ],
+  ], [
+    [
+       0,  7,  4,  6,  4,  7,  6,  7,  6,  9,  7,  8,  7,  9,  8,  8,
+      13, 14, 12, 12, 12, 13, 11, 11,  5,  9,  5,  8,  7,  9,  7,  8,
+       8, 11,  8, 10,  9, 10,  9,  9, 13, 15, 12, 13, 12, 13, 11, 11,
+       9, 14,  8, 11, 11, 13, 10, 10, 11, 15, 10, 12, 12, 13, 10, 11,
+      14, 16, 12, 13, 14, 14, 12, 11,  5,  9,  7,  9,  6,  9,  8,  8,
+       8, 11,  8, 10,  8, 10,  9,  9, 13, 16, 12, 13, 13, 13, 11, 11,
+       7, 11,  8, 10,  9, 11,  9,  9,  9, 13,  9, 11, 10, 11, 10, 10,
+      14, 16, 12, 13, 13, 13, 12, 11, 11, 16, 10, 12, 12, 14, 11, 11,
+      13, 16, 11, 13, 13, 14, 11, 11, 16, 16, 13, 14, 14, 15, 12, 11,
+      10, 15, 11, 13,  9, 12, 10, 10, 12, 16, 12, 13, 11, 12, 11, 11,
+      15, 16, 13, 14, 13, 14, 12, 11, 12, 16, 12, 14, 11, 13, 11, 11,
+      13, 16, 12, 14, 12, 13, 12, 11, 16, 16, 13, 14, 14, 14, 12, 11,
+      14, 16, 13, 14, 14, 15, 12, 12, 16, 16, 13, 14, 14, 16, 12, 12,
+      16, 16, 14, 14, 14, 15, 12, 11,  3,  9,  5,  8,  6,  9,  7,  8,
+       7, 11,  8, 10,  9, 10,  9,  9, 13, 14, 12, 13, 13, 13, 12, 11,
+       6, 11,  6,  9,  8, 10,  8,  9,  9, 12,  8, 10, 10, 11,  9, 10,
+      14, 16, 12, 13, 13, 14, 12, 11,  9, 14,  8, 11, 11, 13, 10, 10,
+      12, 16, 10, 12, 12, 14, 11, 11, 16, 16, 12, 13, 14, 15, 12, 11,
+       6, 11,  8, 10,  7, 10,  8,  9,  9, 12,  9, 11,  9, 11, 10, 10,
+      14, 16, 13, 13, 13, 14, 12, 11,  8, 12,  9, 11,  9, 11,  9, 10,
+      10, 13,  9, 11, 10, 12, 10, 10, 14, 16, 12, 13, 13, 14, 12, 11,
+      12, 16, 10, 12, 12, 14, 11, 11, 12, 16, 10, 12, 13, 14, 11, 11,
+      15, 16, 12, 13, 14, 14, 11, 11, 10, 15, 11, 13,  9, 12, 10, 10,
+      12, 16, 12, 14, 11, 13, 11, 11, 16, 16, 14, 14, 14, 14, 12, 11,
+      12, 16, 12, 14, 11, 13, 11, 11, 13, 16, 12, 14, 11, 13, 11, 11,
+      16, 16, 13, 14, 13, 14, 12, 11, 14, 16, 13, 14, 14, 15, 12, 11,
+      14, 16, 13, 14, 13, 15, 12, 11, 16, 16, 13, 14, 13, 14, 11, 10,
+       6, 13,  8, 11,  9, 12, 10, 10, 10, 14, 10, 12, 11, 13, 11, 11,
+      16, 16, 13, 14, 14, 14, 13, 12,  8, 14,  8, 12, 10, 13, 10, 11,
+      11, 15, 10, 12, 12, 13, 11, 11, 16, 16, 14, 14, 15, 16, 13, 12,
+      11, 16,  9, 12, 12, 14, 11, 11, 13, 16, 11, 13, 13, 16, 11, 11,
+      16, 16, 13, 14, 16, 16, 13, 12,  8, 14, 10, 12,  9, 12, 10, 11,
+      11, 15, 11, 13, 11, 13, 11, 11, 16, 16, 14, 15, 14, 15, 13, 12,
+      10, 15, 10, 13, 11, 13, 11, 11, 11, 15, 11, 13, 12, 13, 11, 11,
+      16, 16, 13, 15, 14, 15, 13, 12, 12, 16, 11, 13, 13, 15, 11, 11,
+      13, 16, 11, 13, 13, 15, 11, 11, 16, 16, 12, 14, 14, 16, 12, 11,
+      11, 16, 12, 14, 10, 13, 11, 11, 13, 16, 13, 15, 12, 14, 12, 12,
+      16, 16, 15, 16, 14, 15, 13, 12, 12, 16, 13, 14, 12, 14, 12, 12,
+      13, 16, 13, 14, 12, 14, 12, 12, 16, 16, 14, 15, 13, 14, 12, 12,
+      15, 16, 13, 15, 14, 16, 12, 12, 14, 16, 13, 14, 13, 15, 12, 12,
+      15, 16, 12, 13, 13, 14, 11, 10,  9, 15, 10, 13, 11, 14, 11, 12,
+      12, 16, 12, 14, 12, 14, 12, 12, 16, 16, 14, 14, 14, 15, 13, 12,
+      10, 16, 10, 13, 12, 14, 12, 12, 13, 16, 12, 14, 13, 15, 12, 12,
+      16, 16, 14, 14, 15, 16, 13, 12, 11, 16,  9, 12, 13, 15, 11, 11,
+      14, 16, 11, 13, 14, 16, 11, 11, 16, 16, 13, 14, 16, 16, 12, 11,
+      10, 16, 11, 14, 11, 14, 12, 12, 13, 16, 13, 14, 12, 14, 12, 12,
+      16, 16, 14, 15, 15, 15, 13, 12, 11, 16, 12, 14, 12, 15, 12, 12,
+      13, 16, 12, 14, 13, 15, 12, 12, 16, 16, 14, 15, 15, 16, 13, 12,
+      12, 16, 11, 13, 13, 15, 11, 11, 13, 16, 11, 13, 13, 15, 11, 11,
+      16, 16, 12, 13, 14, 16, 12, 10, 11, 16, 12, 14, 10, 13, 11, 11,
+      14, 16, 13, 14, 12, 14, 11, 11, 16, 16, 15, 16, 14, 14, 12, 11,
+      12, 16, 13, 14, 11, 14, 11, 11, 13, 16, 13, 14, 12, 14, 11, 11,
+      16, 16, 14, 15, 13, 14, 12, 11, 14, 16, 12, 14, 13, 14, 11, 10,
+      13, 16, 12, 13, 12, 14, 11, 10, 14, 16, 11, 12, 12, 12, 10,  8,
+    ], [
+       0,  8,  4,  9,  5,  9,  8, 10,  6, 11,  8, 11,  9, 12, 11, 12,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 11,  6, 11,  9, 12, 10, 12,
+       9, 13, 10, 13, 11, 16, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 11, 16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 11,  8, 12,  7, 12, 10, 12,
+       8, 13, 10, 13, 10, 13, 12, 14, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 13, 10, 14, 11, 16, 12, 14, 11, 16, 12, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 14, 16, 12, 16, 16, 16, 13, 16, 16, 16, 14, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 10,  5, 10,  7, 11,  9, 11,
+       8, 12,  9, 12, 10, 13, 12, 13, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 12,  7, 12, 10, 13, 11, 12,  9, 16, 10, 13, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 14, 16,
+      14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       6, 12,  9, 13,  8, 12, 11, 13, 10, 16, 11, 16, 11, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 10, 14, 11, 16, 12, 16,
+      10, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 14, 16, 11, 16, 14, 16,
+      16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       6, 16,  9, 13, 10, 16, 12, 14, 11, 16, 12, 16, 12, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16,  9, 14, 12, 16, 13, 16,
+      12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 10, 16, 16, 16, 14, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 11, 16, 10, 16, 12, 16,
+      12, 16, 13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 13, 16, 14, 16, 11, 16, 13, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16,
+      14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 11, 16, 14, 16, 16, 16, 16, 16, 14, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 11, 16, 12, 16, 13, 16,
+      13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 11, 16, 13, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 13, 16,
+      16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 12, 16, 13, 16, 13, 16, 16, 16, 14, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 14, 16, 16, 16,
+      13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 12, 16, 16, 16, 14, 16, 14, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 11, 16, 13, 16,
+      16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 14, 15,
+    ],
+  ], [
+    [
+       0,  7,  3,  7,  4,  7,  6,  7,  6,  9,  7,  9,  7,  9,  8,  9,
+      13, 14, 12, 13, 13, 13, 12, 12,  4,  9,  5,  9,  7,  9,  8,  9,
+       7, 11,  8, 10,  9, 11,  9, 10, 13, 16, 12, 14, 13, 14, 12, 12,
+       9, 14,  8, 12, 12, 14, 10, 11, 11, 16, 10, 13, 13, 14, 11, 12,
+      15, 16, 13, 14, 14, 16, 12, 12,  5, 10,  7,  9,  6,  9,  8,  9,
+       8, 11,  8, 11,  8, 10,  9, 10, 14, 16, 12, 14, 13, 14, 12, 12,
+       7, 12,  8, 11,  9, 11,  9, 10,  9, 13,  9, 12, 10, 12, 10, 11,
+      14, 16, 12, 14, 13, 14, 12, 12, 12, 16, 11, 13, 13, 15, 11, 12,
+      13, 16, 11, 14, 13, 15, 12, 12, 15, 16, 13, 15, 14, 16, 13, 13,
+      10, 15, 12, 14,  9, 13, 11, 12, 12, 16, 12, 14, 11, 13, 12, 12,
+      15, 16, 13, 15, 14, 15, 13, 13, 12, 16, 12, 14, 12, 14, 12, 12,
+      13, 16, 13, 14, 12, 14, 12, 12, 16, 16, 14, 15, 14, 16, 13, 13,
+      15, 16, 13, 15, 14, 16, 12, 13, 16, 16, 14, 16, 14, 16, 13, 13,
+      16, 16, 14, 16, 15, 16, 13, 13,  3,  9,  5,  9,  6,  9,  8,  9,
+       7, 11,  8, 10,  9, 11,  9, 10, 14, 15, 13, 14, 13, 14, 12, 12,
+       5, 11,  6, 10,  8, 11,  9, 10,  9, 12,  9, 11, 10, 12, 10, 11,
+      14, 16, 13, 14, 14, 15, 13, 13,  9, 15,  8, 12, 12, 14, 10, 11,
+      12, 16, 10, 13, 13, 15, 11, 12, 15, 16, 13, 14, 14, 16, 13, 13,
+       6, 11,  8, 11,  7, 10,  9, 10,  9, 13, 10, 12,  9, 12, 10, 11,
+      14, 16, 13, 14, 14, 14, 13, 13,  8, 13,  9, 12,  9, 12, 10, 11,
+       9, 13,  9, 12, 10, 12, 10, 11, 14, 16, 12, 14, 13, 14, 12, 12,
+      12, 16, 11, 13, 13, 15, 11, 12, 12, 16, 11, 13, 13, 15, 11, 12,
+      14, 16, 12, 14, 14, 15, 12, 12, 10, 15, 11, 14,  9, 13, 11, 12,
+      12, 16, 12, 14, 11, 14, 12, 12, 16, 16, 14, 16, 14, 15, 13, 13,
+      12, 16, 12, 14, 11, 14, 12, 12, 12, 16, 13, 14, 11, 14, 12, 12,
+      15, 16, 14, 15, 13, 15, 12, 13, 14, 16, 13, 15, 14, 16, 13, 13,
+      14, 16, 13, 15, 14, 16, 12, 13, 15, 16, 13, 15, 13, 15, 12, 12,
+       6, 13,  8, 12,  9, 12, 10, 11, 10, 14, 11, 13, 11, 13, 12, 12,
+      15, 16, 14, 15, 15, 15, 14, 13,  8, 14,  9, 12, 11, 13, 11, 12,
+      11, 15, 11, 13, 12, 14, 12, 12, 16, 16, 14, 15, 15, 16, 14, 14,
+      10, 16,  9, 13, 12, 15, 11, 12, 13, 16, 11, 14, 13, 16, 12, 12,
+      16, 16, 14, 15, 16, 16, 13, 13,  8, 14, 10, 13,  9, 13, 11, 12,
+      11, 15, 12, 14, 11, 14, 12, 12, 16, 16, 15, 16, 15, 16, 14, 14,
+      10, 15, 10, 13, 11, 14, 11, 12, 11, 15, 11, 14, 12, 14, 12, 12,
+      15, 16, 14, 15, 14, 16, 13, 13, 12, 16, 11, 14, 13, 16, 12, 12,
+      12, 16, 11, 14, 13, 15, 12, 12, 15, 16, 12, 14, 15, 16, 13, 13,
+      11, 16, 12, 14, 10, 14, 11, 12, 13, 16, 13, 16, 12, 14, 12, 13,
+      16, 16, 16, 16, 15, 16, 14, 13, 12, 16, 13, 15, 12, 14, 12, 13,
+      13, 16, 13, 15, 12, 14, 12, 13, 16, 16, 14, 16, 13, 15, 13, 13,
+      15, 16, 14, 16, 14, 16, 13, 13, 14, 16, 13, 15, 13, 16, 13, 13,
+      14, 16, 12, 14, 13, 14, 12, 12,  9, 16, 11, 14, 11, 15, 12, 13,
+      13, 16, 12, 14, 12, 15, 13, 13, 16, 16, 14, 15, 15, 15, 14, 13,
+      11, 16, 11, 14, 12, 16, 12, 13, 13, 16, 12, 14, 13, 16, 13, 13,
+      16, 16, 14, 15, 16, 16, 14, 13, 11, 16, 10, 13, 13, 16, 11, 12,
+      14, 16, 11, 14, 14, 16, 12, 12, 16, 16, 14, 14, 16, 16, 13, 12,
+      11, 16, 12, 14, 11, 15, 12, 13, 13, 16, 13, 15, 13, 16, 13, 13,
+      16, 16, 15, 16, 15, 16, 14, 13, 11, 16, 12, 15, 12, 16, 12, 13,
+      13, 16, 13, 15, 13, 16, 13, 13, 16, 16, 15, 16, 15, 16, 14, 13,
+      12, 16, 11, 14, 13, 16, 12, 12, 13, 16, 11, 14, 13, 16, 12, 12,
+      16, 16, 13, 14, 15, 16, 12, 12, 11, 16, 12, 14, 10, 14, 11, 12,
+      14, 16, 13, 15, 12, 15, 12, 12, 16, 16, 16, 16, 14, 15, 13, 12,
+      12, 16, 13, 15, 12, 14, 12, 12, 13, 16, 13, 15, 12, 14, 12, 12,
+      16, 16, 14, 16, 14, 15, 12, 12, 14, 16, 13, 15, 13, 16, 11, 12,
+      13, 16, 12, 14, 13, 15, 11, 11, 14, 16, 12, 13, 12, 13, 11, 10,
+    ], [
+       0,  8,  4,  9,  5, 10,  9, 11,  5, 11,  9, 12,  9, 13, 12, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 11,  6, 12,  9, 13, 11, 13,
+       9, 16, 10, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 12,  8, 13,  7, 12, 11, 16,
+       8, 16, 11, 16, 11, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 10, 16, 11, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 10,  6, 11,  7, 12, 10, 13,
+       7, 12, 10, 13, 10, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 13,  7, 12, 10, 16, 12, 16, 10, 16, 11, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 16, 16,
+      16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 13,  9, 16,  8, 16, 12, 16,  9, 16, 12, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 11, 16, 12, 16, 13, 16,
+      10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       6, 16,  9, 16, 10, 16, 13, 16, 11, 16, 12, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16,  9, 16, 12, 16, 13, 16,
+      12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 10, 16, 16, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 11, 16, 11, 16, 13, 16,
+      12, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 13, 16, 16, 16, 11, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 16, 11, 16, 12, 16, 16, 16,
+      13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 11, 16, 13, 16, 16, 16, 16, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 10, 16, 16, 16, 16, 16,
+      16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 16, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  7,  4,  8,  4,  8,  7,  8,  6, 10,  7, 10,  8, 10,  9, 10,
+      13, 16, 13, 15, 13, 15, 13, 14,  4, 10,  5, 10,  7, 10,  9, 10,
+       7, 12,  8, 11,  9, 12, 10, 11, 13, 16, 13, 15, 13, 16, 13, 14,
+       9, 16,  9, 13, 12, 16, 11, 13, 11, 16, 11, 14, 13, 16, 12, 14,
+      15, 16, 14, 16, 15, 16, 14, 14,  4, 10,  7, 10,  6, 10,  9, 10,
+       8, 12,  9, 12,  9, 11, 10, 12, 13, 16, 13, 16, 14, 16, 13, 14,
+       7, 12,  8, 12,  9, 12, 10, 12,  9, 13, 10, 13, 10, 13, 11, 12,
+      14, 16, 13, 16, 14, 16, 13, 14, 12, 16, 11, 14, 13, 16, 12, 14,
+      13, 16, 12, 16, 14, 16, 13, 14, 16, 16, 14, 16, 15, 16, 14, 14,
+      10, 16, 12, 15, 10, 14, 12, 13, 12, 16, 13, 16, 12, 14, 13, 14,
+      15, 16, 14, 16, 14, 16, 14, 14, 12, 16, 13, 16, 12, 16, 13, 14,
+      13, 16, 13, 16, 13, 16, 13, 14, 16, 16, 14, 16, 15, 16, 14, 15,
+      15, 16, 14, 16, 15, 16, 13, 15, 16, 16, 14, 16, 15, 16, 14, 15,
+      16, 16, 16, 16, 16, 16, 15, 15,  2,  9,  5, 10,  6, 10,  8, 10,
+       7, 11,  8, 11,  9, 11, 10, 11, 14, 16, 13, 15, 14, 15, 14, 14,
+       5, 11,  6, 11,  8, 12,  9, 11,  8, 13,  9, 12, 10, 13, 11, 12,
+      14, 16, 13, 15, 14, 16, 14, 14,  9, 16,  8, 13, 12, 16, 11, 13,
+      12, 16, 11, 14, 13, 16, 12, 13, 16, 16, 14, 16, 15, 16, 14, 15,
+       5, 12,  8, 11,  7, 11,  9, 11,  9, 13, 10, 13, 10, 13, 11, 12,
+      14, 16, 14, 16, 14, 16, 14, 15,  8, 13,  9, 13, 10, 13, 11, 12,
+       9, 13, 10, 13, 10, 13, 11, 13, 13, 16, 13, 15, 13, 16, 13, 14,
+      12, 16, 11, 14, 13, 16, 12, 14, 12, 16, 11, 14, 13, 16, 12, 14,
+      14, 16, 13, 16, 14, 16, 13, 14, 10, 16, 12, 15,  9, 14, 11, 13,
+      12, 16, 13, 16, 12, 15, 12, 14, 16, 16, 15, 16, 15, 16, 14, 14,
+      12, 16, 13, 16, 12, 16, 12, 14, 12, 16, 13, 16, 12, 15, 13, 14,
+      15, 16, 14, 16, 14, 16, 14, 14, 15, 16, 14, 16, 14, 16, 14, 15,
+      14, 16, 13, 16, 14, 16, 13, 14, 16, 16, 14, 16, 14, 16, 13, 14,
+       6, 14,  9, 13,  9, 14, 11, 12, 10, 14, 11, 13, 11, 14, 12, 13,
+      16, 16, 15, 16, 15, 16, 14, 15,  8, 15,  9, 13, 11, 14, 11, 13,
+      11, 16, 11, 14, 12, 15, 12, 14, 16, 16, 15, 16, 16, 16, 15, 16,
+      10, 16,  9, 14, 12, 16, 12, 13, 13, 16, 11, 15, 14, 16, 13, 14,
+      16, 16, 15, 16, 16, 16, 15, 16,  8, 15, 10, 13, 10, 14, 11, 13,
+      11, 16, 12, 14, 12, 14, 12, 14, 16, 16, 16, 16, 16, 16, 15, 16,
+      10, 16, 11, 14, 11, 15, 12, 13, 11, 16, 11, 14, 12, 15, 12, 14,
+      16, 16, 14, 16, 15, 16, 14, 15, 12, 16, 11, 15, 13, 16, 13, 14,
+      12, 16, 11, 14, 13, 16, 13, 14, 15, 16, 13, 16, 16, 16, 14, 15,
+      10, 16, 12, 15, 10, 15, 12, 13, 13, 16, 13, 16, 12, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 15, 12, 16, 13, 16, 12, 16, 13, 14,
+      12, 16, 13, 16, 12, 16, 13, 14, 16, 16, 15, 16, 14, 16, 14, 15,
+      15, 16, 14, 16, 15, 16, 14, 15, 14, 16, 13, 16, 14, 16, 13, 14,
+      14, 16, 13, 15, 14, 16, 13, 14,  9, 16, 11, 16, 11, 16, 12, 14,
+      13, 16, 12, 16, 13, 16, 13, 14, 16, 16, 15, 16, 16, 16, 15, 15,
+      11, 16, 11, 16, 12, 16, 13, 14, 13, 16, 12, 16, 13, 16, 13, 14,
+      16, 16, 15, 16, 16, 16, 15, 15, 11, 16, 10, 15, 13, 16, 12, 13,
+      14, 16, 12, 16, 14, 16, 13, 14, 16, 16, 15, 16, 16, 16, 14, 14,
+      11, 16, 12, 16, 11, 16, 13, 14, 13, 16, 13, 16, 13, 16, 13, 14,
+      16, 16, 16, 16, 16, 16, 15, 15, 11, 16, 12, 16, 12, 16, 13, 14,
+      13, 16, 13, 16, 13, 16, 13, 14, 16, 16, 15, 16, 16, 16, 15, 14,
+      12, 16, 12, 15, 13, 16, 12, 14, 13, 16, 12, 16, 14, 16, 13, 14,
+      16, 16, 14, 16, 16, 16, 14, 14, 11, 16, 12, 16, 11, 16, 12, 14,
+      14, 16, 14, 16, 12, 16, 13, 14, 16, 16, 16, 16, 16, 16, 15, 14,
+      12, 16, 13, 16, 12, 16, 12, 14, 13, 16, 13, 16, 12, 16, 13, 14,
+      16, 16, 16, 16, 15, 16, 14, 14, 14, 16, 13, 16, 14, 16, 12, 14,
+      13, 16, 13, 16, 13, 16, 12, 13, 15, 16, 13, 14, 14, 15, 13, 13,
+    ], [
+       0,  8,  4, 10,  5, 11, 10, 16,  5, 12,  9, 16, 10, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 12,  7, 12,  9, 16, 12, 16,
+       9, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 12,  9, 16,  8, 16, 12, 16,
+       8, 16, 11, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       8, 16, 11, 16, 12, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 11,  6, 12,  7, 16, 11, 16,
+       7, 16, 10, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16,  7, 16, 10, 16, 12, 16,  9, 16, 11, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16, 10, 16,  8, 16, 12, 16,  9, 16, 12, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 11, 16, 12, 16, 16, 16,
+      10, 16, 12, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16,  9, 16, 10, 16, 16, 16, 11, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16,  9, 16, 12, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 11, 16, 11, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      11, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 10, 16, 12, 16, 16, 16,
+      12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16,  9, 16, 16, 16, 16, 16,
+      16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      13, 16, 12, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  8,  4, 10,  5,  9,  8, 10,  6, 11,  8, 12,  8, 11, 10, 13,
+      14, 16, 14, 16, 14, 16, 16, 16,  3, 11,  5, 11,  8, 12, 10, 12,
+       7, 12,  9, 13, 10, 13, 11, 13, 14, 16, 14, 16, 16, 16, 16, 16,
+       9, 16,  9, 16, 12, 16, 12, 16, 11, 16, 11, 16, 14, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 11,  7, 12,  6, 11, 10, 12,
+       8, 13,  9, 13,  9, 13, 11, 14, 13, 16, 14, 16, 14, 16, 16, 16,
+       7, 13,  9, 13,  9, 13, 11, 13,  9, 14, 10, 16, 11, 16, 12, 16,
+      15, 16, 14, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 13, 16,
+      13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 10, 16, 13, 16, 12, 16, 13, 16, 12, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 13, 16, 14, 16,
+      13, 16, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  2, 10,  5, 11,  6, 11,  9, 11,
+       7, 12,  9, 13,  9, 13, 11, 13, 14, 16, 16, 16, 16, 16, 16, 16,
+       4, 12,  6, 12,  8, 13, 10, 13,  8, 13,  9, 13, 11, 16, 12, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16,  8, 16, 12, 16, 12, 16,
+      12, 16, 11, 16, 13, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 12,  8, 13,  7, 13, 10, 13,  8, 14, 10, 14, 10, 14, 12, 14,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 14,  9, 16, 10, 16, 11, 14,
+       8, 14, 10, 16, 11, 16, 12, 16, 13, 16, 14, 16, 16, 16, 16, 16,
+      11, 16, 11, 16, 13, 16, 13, 16, 12, 16, 12, 16, 14, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 12, 16, 10, 16, 12, 16,
+      12, 16, 13, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 13, 16, 12, 16, 14, 16, 12, 16, 13, 16, 12, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       6, 16,  8, 16,  9, 16, 11, 13, 10, 16, 11, 16, 11, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 16,  9, 16, 10, 16, 12, 16,
+      11, 16, 11, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16,  9, 16, 12, 16, 13, 16, 13, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  7, 16, 10, 16,  9, 16, 12, 16,
+      11, 16, 12, 16, 12, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16, 11, 16, 11, 16, 12, 16, 11, 16, 12, 16, 13, 16, 13, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 12, 16, 14, 16, 14, 16,
+      12, 16, 12, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 10, 16, 13, 16, 13, 16, 14, 16, 13, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 13, 16, 12, 16, 14, 16,
+      12, 16, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 11, 16, 11, 16, 13, 16,
+      12, 16, 13, 16, 13, 16, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 11, 16, 13, 16, 13, 16, 13, 16, 13, 16, 14, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 11, 16, 14, 16, 13, 16,
+      14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 12, 16, 12, 16, 13, 16, 13, 16, 13, 16, 13, 16, 14, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 12, 16, 13, 16, 14, 16,
+      13, 16, 13, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 12, 16, 14, 16, 14, 16, 14, 16, 14, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 13, 16, 11, 16, 14, 16,
+      16, 16, 16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 14, 16, 13, 16, 14, 16, 16, 16, 16, 16, 14, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       0, 10,  4, 12,  5, 16, 11, 16,  6, 16, 10, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  3, 16,  7, 16, 10, 16, 16, 16,
+       9, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  4, 16, 10, 16,  9, 16, 16, 16,
+       9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16, 12, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  1, 16,  6, 16,  8, 16, 16, 16,
+       8, 16, 11, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16,  8, 16, 11, 16, 16, 16, 10, 16, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 11, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16, 11, 16,  9, 16, 16, 16, 10, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  9, 16, 12, 16, 16, 16, 16, 16,
+      10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       5, 16,  9, 16, 11, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 10, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  8, 16, 16, 16, 11, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      12, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,  6, 16, 11, 16, 15, 16, 16, 16,
+      15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       9, 16, 10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16,  9, 16, 16, 16, 16, 16,
+      16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      10, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ],
+];
+
+const RV34_INTER_SECONDPAT: &'static [[[u8; 108]; 2]; 7] = &[
+  [
+    [
+       0,  4,  8,  3,  6,  8,  6,  7,  8,  4,  6,  8,  6,  7,  8,  7,
+       8,  8,  7,  8,  8,  8,  8,  8,  8,  8,  8,  3,  6,  8,  4,  6,
+       9,  7,  7,  8,  5,  7,  9,  6,  7,  9,  8,  8,  8,  7,  8,  8,
+       8,  8,  8,  8,  8,  7,  6,  8,  9,  7,  8,  9,  7,  8,  9,  7,
+       8,  9,  7,  8,  9,  8,  8,  9,  8,  8,  9,  8,  9,  9,  8,  8,
+       8,  8,  9,  9,  8,  9,  9,  7,  8,  8,  8,  9,  9,  8,  9,  9,
+       8,  8,  8,  7,  8,  8,  8,  8,  8,  7,  7,  6,
+    ], [
+       0,  4,  9,  3,  6,  9,  7,  8, 10,  3,  6,  9,  5,  7, 10,  9,
+       9, 10,  7,  8, 10,  8,  9, 10, 10, 10, 10,  2,  6,  9,  4,  7,
+      10,  8,  9, 10,  4,  7, 10,  6,  7, 10,  9,  9, 10,  7,  8, 10,
+       8,  9, 10, 10, 10, 10,  6,  8, 10,  7,  9, 11,  9, 10, 11,  7,
+       9, 11,  8,  9, 11, 10, 10, 11,  8,  9, 11,  9, 10, 11, 11, 11,
+      10,  8, 10, 11,  9, 10, 11,  9, 10, 11,  8, 10, 11,  9, 10, 11,
+      10, 10, 11,  8, 10, 11,  9, 10, 10, 10, 10,  9,
+    ],
+  ], [
+    [
+       0,  4,  8,  3,  6,  8,  6,  7,  9,  4,  6,  8,  5,  7,  8,  8,
+       8,  9,  7,  7,  8,  8,  8,  8,  8,  9,  8,  3,  6,  8,  4,  6,
+       9,  7,  7,  9,  5,  6,  9,  6,  7,  9,  8,  8,  9,  7,  8,  8,
+       8,  8,  8,  8,  8,  8,  6,  8,  9,  7,  8, 10,  7,  8,  9,  7,
+       8, 10,  7,  8, 10,  8,  8,  9,  7,  8,  9,  8,  9,  9,  9,  9,
+       8,  7,  9, 10,  8,  9, 10,  8,  8,  8,  8,  9, 10,  8,  9,  9,
+       8,  8,  8,  7,  8,  8,  8,  8,  8,  8,  7,  6,
+    ], [
+       0,  4,  9,  3,  6, 10,  8,  9, 11,  3,  5,  9,  5,  7, 10,  9,
+      10, 11,  7,  8, 10,  9,  9, 11, 11, 11, 12,  2,  5, 10,  4,  7,
+      10,  8,  9, 11,  4,  6, 10,  6,  7, 10,  9, 10, 11,  7,  9, 10,
+       9,  9, 11, 11, 11, 11,  6,  8, 11,  7,  9, 11,  9, 10, 12,  7,
+       9, 11,  8,  9, 12, 10, 10, 12,  8, 10, 11, 10, 10, 11, 12, 11,
+      11,  8, 10, 12,  9, 11, 12, 10, 11, 12,  9, 10, 12, 10, 11, 12,
+      11, 11, 12,  9, 10, 12, 10, 10, 11, 11, 11, 10,
+    ],
+  ], [
+    [
+       0,  4,  8,  3,  6,  9,  7,  8,  9,  4,  6,  8,  5,  7,  9,  8,
+       9,  9,  7,  8,  9,  8,  8,  9,  9,  9,  9,  2,  6,  9,  4,  6,
+       9,  7,  8, 10,  5,  7,  9,  6,  7,  9,  8,  8,  9,  7,  8,  9,
+       8,  8,  9,  9,  9,  9,  6,  8, 10,  7,  8, 10,  8,  9, 10,  6,
+       8, 10,  8,  8, 10,  9,  9, 10,  8,  9, 10,  9,  9, 10, 10, 10,
+       9,  8,  9, 10,  8,  9, 10,  8,  9, 10,  8,  9, 10,  9,  9, 10,
+       9,  9,  9,  8,  9,  9,  8,  9,  9,  9,  9,  8,
+    ], [
+       0,  4, 10,  3,  6, 10,  8, 10, 12,  2,  6, 10,  6,  8, 11, 10,
+      11, 12,  7,  9, 11,  9, 10, 12, 12, 13, 13,  2,  6, 10,  4,  7,
+      11,  9, 10, 13,  4,  7, 11,  7,  8, 11, 10, 11, 12,  8,  9, 12,
+      10, 10, 12, 12, 12, 13,  6,  9, 12,  8, 10, 13, 10, 12, 14,  7,
+      10, 13,  9, 10, 13, 11, 11, 13,  9, 11, 13, 11, 11, 13, 13, 13,
+      13,  9, 11, 13, 10, 12, 14, 11, 12, 14,  9, 11, 14, 11, 12, 14,
+      12, 12, 14,  9, 12, 13, 11, 12, 13, 13, 12, 12,
+    ],
+  ], [
+    [
+       0,  4,  9,  3,  6,  9,  7,  8, 10,  3,  6,  9,  6,  7,  9,  9,
+       9, 10,  7,  8,  9,  8,  9, 10, 10, 10, 11,  2,  6,  9,  4,  7,
+      10,  7,  9, 10,  4,  7, 10,  6,  7, 10,  9,  9, 10,  7,  8, 10,
+       8,  9, 10, 10, 10, 10,  6,  8, 11,  7,  9, 11,  8, 10, 11,  6,
+       9, 11,  8,  9, 11,  9,  9, 11,  8,  9, 11,  9, 10, 11, 11, 10,
+      10,  8, 10, 11,  9, 10, 11,  9, 10, 11,  8, 10, 11,  9, 10, 11,
+      10, 10, 11,  8, 10, 11,  9, 10, 11, 10, 10, 10,
+    ], [
+       0,  4, 12,  3,  7, 12, 10, 11, 14,  3,  6, 12,  7,  9, 13, 12,
+      13, 14,  8, 11, 13, 11, 12, 14, 14, 14, 14,  1,  7, 12,  5,  8,
+      13, 10, 12, 14,  4,  8, 13,  8,  9, 13, 12, 13, 14,  9, 11, 14,
+      11, 12, 14, 14, 14, 14,  7, 10, 14,  9, 11, 14, 11, 13, 16,  8,
+      11, 14, 10, 12, 14, 13, 13, 16, 10, 12, 15, 12, 13, 15, 15, 15,
+      15, 10, 13, 15, 12, 13, 14, 13, 15, 15, 10, 13, 15, 12, 13, 15,
+      13, 14, 15, 10, 13, 14, 12, 13, 14, 14, 14, 14,
+    ],
+  ], [
+    [
+       0,  4,  9,  3,  6, 10,  7,  9, 11,  3,  5,  9,  5,  7, 10,  9,
+      10, 12,  7,  8, 10,  9, 10, 11, 11, 12, 12,  2,  6, 10,  4,  7,
+      10,  7,  9, 12,  4,  7, 10,  6,  7, 11,  9, 10, 12,  7,  9, 11,
+       9,  9, 11, 11, 11, 12,  5,  8, 11,  7,  9, 12,  9, 10, 13,  6,
+       9, 12,  8,  9, 12, 10, 10, 12,  8, 10, 12, 10, 10, 12, 12, 12,
+      12,  8, 10, 12,  9, 11, 13, 10, 11, 13,  9, 11, 13, 10, 11, 13,
+      11, 11, 13,  9, 11, 12, 10, 11, 12, 11, 11, 12,
+    ], [
+       0,  4, 12,  3,  7, 13, 10, 12, 15,  3,  7, 13,  7,  9, 14, 12,
+      12, 13,  8, 11, 14, 11, 13, 15, 15, 14, 14,  1,  6, 13,  5,  8,
+      13, 10, 13, 15,  4,  8, 13,  8,  9, 14, 13, 13, 15,  8, 11, 14,
+      12, 12, 15, 15, 14, 14,  7, 10, 13,  9, 11, 13, 12, 14, 16,  8,
+      11, 14, 10, 12, 15, 13, 13, 16, 10, 12, 15, 12, 13, 15, 15, 14,
+      15, 11, 12, 14, 12, 14, 14, 13, 15, 15, 10, 12, 14, 12, 13, 15,
+      14, 15, 15, 10, 13, 13, 12, 13, 15, 14, 14, 15,
+    ],
+  ], [
+    [
+       0,  5, 10,  3,  7, 11,  9, 11, 14,  3,  7, 11,  7,  8, 12, 11,
+      12, 14,  7,  9, 12, 10, 11, 14, 13, 14, 16,  1,  7, 11,  5,  8,
+      12,  9, 11, 15,  4,  8, 12,  7,  9, 13, 11, 12, 15,  8, 10, 13,
+      10, 11, 14, 14, 14, 16,  6,  9, 13,  8, 11, 14, 10, 13, 16,  7,
+      10, 14,  9, 11, 15, 12, 13, 16,  9, 11, 15, 12, 12, 15, 14, 14,
+      16, 10, 12, 14, 11, 13, 15, 12, 14, 16, 10, 12, 15, 11, 13, 16,
+      13, 14, 16, 10, 13, 16, 12, 13, 15, 14, 15, 16,
+    ], [
+       0,  5, 16,  3,  8, 14, 11, 13, 14,  2,  8, 14,  8, 10, 16, 13,
+      13, 14,  9, 13, 16, 12, 13, 16, 16, 14, 16,  1,  7, 14,  6, 10,
+      14, 12, 16, 16,  5,  9, 14,  9, 11, 16, 15, 16, 16, 10, 12, 16,
+      13, 13, 16, 16, 14, 16,  8, 11, 14, 11, 13, 14, 14, 14, 16,  8,
+      12, 14, 11, 13, 16, 16, 16, 16, 10, 12, 15, 13, 14, 16, 16, 16,
+      16, 11, 14, 14, 14, 15, 16, 16, 15, 16, 10, 13, 16, 13, 14, 14,
+      16, 16, 16, 10, 13, 16, 13, 14, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  5, 11,  3,  7, 13,  9, 12, 16,  3,  7, 12,  6,  9, 14, 11,
+      13, 16,  7, 10, 16, 11, 12, 16, 16, 16, 16,  1,  6, 12,  5,  9,
+      16,  9, 13, 16,  4,  8, 16,  7, 10, 16, 12, 15, 16,  7, 11, 16,
+      11, 12, 16, 16, 16, 16,  6, 10, 15,  8, 11, 16, 11, 14, 16,  7,
+      11, 16, 10, 12, 16, 13, 16, 16,  9, 13, 16, 13, 14, 16, 16, 16,
+      16, 10, 12, 16, 12, 16, 16, 16, 16, 16, 11, 13, 16, 13, 16, 16,
+      16, 16, 16, 12, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       0,  5, 16,  3,  8, 16, 12, 12, 16,  2,  8, 16,  8, 10, 16, 13,
+      13, 16,  9, 13, 16, 12, 13, 16, 16, 16, 16,  1,  8, 16,  6, 10,
+      16, 12, 16, 16,  5,  9, 16,  9, 11, 16, 13, 16, 16,  9, 12, 14,
+      12, 12, 16, 16, 16, 16,  8, 11, 13, 11, 12, 16, 14, 16, 16,  8,
+      12, 16, 11, 13, 16, 16, 15, 16,  9, 13, 14, 12, 13, 16, 16, 16,
+      16, 10, 12, 13, 14, 13, 16, 16, 16, 16,  9, 13, 16, 13, 12, 16,
+      16, 16, 16, 10, 12, 16, 14, 15, 16, 16, 16, 16,
+    ],
+  ],
+];
+
+const RV34_INTER_THIRDPAT: &'static [[[u8; 108]; 2]; 7] = &[
+  [
+    [
+       0,  5,  8,  3,  6,  9,  6,  7,  9,  4,  6,  9,  6,  7,  9,  8,
+       8,  9,  7,  8,  9,  8,  9,  9,  9,  9,  9,  2,  6,  9,  4,  7,
+       9,  7,  8,  9,  5,  7,  9,  6,  7,  9,  8,  8,  9,  7,  8,  9,
+       8,  9,  9,  9,  9,  8,  5,  8, 10,  6,  8, 10,  8,  9,  9,  7,
+       8, 10,  7,  9, 10,  8,  9,  9,  8,  9, 10,  9,  9, 10,  9,  9,
+       9,  7,  9, 10,  8,  9, 10,  8,  8,  9,  8,  9, 10,  8,  9, 10,
+       8,  8,  9,  8,  9,  9,  8,  9,  9,  8,  8,  7,
+    ], [
+       0,  4,  9,  2,  6, 10,  7,  8, 10,  3,  6, 10,  6,  7, 10,  9,
+       9, 10,  8,  9, 11,  9, 10, 11, 10, 11, 11,  2,  6, 10,  4,  7,
+      10,  8,  9, 10,  5,  7, 10,  7,  8, 10,  9,  9, 10,  9, 10, 11,
+      10, 10, 11, 11, 11, 11,  6,  9, 11,  7,  9, 11,  9, 10, 12,  8,
+       9, 11,  8, 10, 11, 10, 10, 11, 10, 11, 12, 11, 11, 12, 11, 11,
+      11,  9, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12,
+      11, 11, 12, 11, 12, 12, 11, 12, 12, 12, 11, 11,
+    ],
+  ], [
+    [
+       0,  4,  9,  3,  6,  9,  6,  8,  9,  4,  6,  9,  5,  7,  9,  8,
+       8,  9,  7,  8, 10,  8,  9, 10,  9,  9,  9,  2,  6,  9,  4,  7,
+       9,  7,  8,  9,  5,  7,  9,  6,  7, 10,  8,  9,  9,  7,  9, 10,
+       8,  9, 10,  9,  9,  9,  5,  8, 10,  6,  8, 10,  8,  9, 10,  7,
+       8, 10,  7,  9, 11,  9,  9, 10,  8,  9, 10,  9, 10, 10, 10, 10,
+       9,  7,  9, 10,  8,  9, 11,  8,  9, 10,  8,  9, 11,  8,  9, 11,
+       9,  9, 10,  9,  9, 10,  9,  9, 10,  9,  9,  8,
+    ], [
+       0,  4,  9,  2,  5, 10,  7,  8, 11,  3,  6, 10,  6,  7, 10,  9,
+      10, 11,  8,  9, 11,  9, 10, 11, 11, 11, 12,  2,  6, 10,  4,  7,
+      10,  8,  9, 11,  5,  7, 10,  6,  8, 10,  9, 10, 11,  9, 10, 12,
+      10, 10, 12, 11, 12, 12,  6,  9, 11,  8,  9, 12,  9, 11, 13,  8,
+      10, 12,  9, 10, 12, 11, 11, 12, 10, 12, 13, 11, 12, 13, 13, 12,
+      13, 10, 11, 13, 10, 12, 13, 11, 12, 13, 11, 12, 13, 11, 12, 13,
+      12, 12, 13, 12, 13, 14, 13, 13, 14, 13, 13, 13,
+    ],
+  ], [
+    [
+       0,  4,  9,  3,  6,  9,  7,  8, 10,  3,  6,  9,  5,  7, 10,  8,
+       9, 10,  7,  9, 10,  8,  9, 10, 10, 10, 10,  2,  6,  9,  4,  7,
+      10,  7,  9, 10,  4,  7, 10,  6,  8, 10,  8,  9, 10,  8,  9, 10,
+       9,  9, 10, 10, 10, 10,  5,  8, 11,  7,  9, 11,  8, 10, 11,  7,
+       9, 11,  8,  9, 11,  9, 10, 11,  9, 10, 11, 10, 10, 11, 11, 11,
+      11,  8, 10, 11,  9, 10, 11,  9, 10, 11,  9, 10, 12,  9, 10, 12,
+      10, 11, 11,  9, 10, 11, 10, 11, 11, 10, 10, 10,
+    ], [
+       0,  4, 10,  3,  6, 11,  8, 10, 12,  3,  6, 11,  6,  8, 11, 10,
+      11, 13,  9, 10, 13, 11, 12, 14, 13, 13, 14,  1,  6, 10,  5,  8,
+      12,  9, 10, 13,  5,  8, 11,  7,  9, 12, 11, 11, 13, 10, 12, 13,
+      11, 12, 14, 14, 13, 15,  7, 10, 12,  9, 11, 14, 11, 12, 15,  9,
+      11, 13, 10, 11, 14, 12, 12, 14, 12, 14, 16, 13, 13, 16, 14, 14,
+      16, 12, 13, 15, 12, 14, 15, 13, 14, 16, 13, 14, 16, 14, 14, 16,
+      14, 15, 16, 14, 16, 16, 15, 16, 16, 15, 15, 16,
+    ],
+  ], [
+    [
+       0,  4,  9,  2,  6,  9,  7,  9, 11,  3,  6, 10,  6,  7, 10,  9,
+      10, 11,  7,  9, 10,  9, 10, 11, 11, 11, 12,  2,  6, 10,  4,  7,
+      10,  8,  9, 11,  5,  7, 10,  7,  8, 10,  9, 10, 11,  8,  9, 11,
+       9, 10, 11, 11, 12, 11,  6,  9, 11,  7, 10, 12,  9, 11, 12,  7,
+      10, 12,  9, 10, 12, 11, 11, 12,  9, 11, 12, 10, 11, 12, 12, 12,
+      12,  9, 11, 12,  9, 11, 13, 11, 12, 13,  9, 11, 13, 10, 12, 13,
+      11, 12, 13, 11, 12, 13, 11, 12, 13, 12, 13, 12,
+    ], [
+       0,  4, 11,  2,  6, 12,  9, 11, 16,  4,  7, 12,  7,  9, 15, 11,
+      12, 16, 10, 11, 16, 11, 13, 16, 16, 16, 16,  1,  6, 11,  5,  8,
+      16,  9, 12, 16,  6,  9, 15,  8, 10, 16, 12, 13, 16, 12, 14, 16,
+      12, 16, 16, 16, 16, 16,  8, 11, 14, 10, 12, 16, 12, 16, 16, 10,
+      13, 16, 12, 16, 16, 13, 14, 16, 14, 16, 16, 16, 16, 16, 16, 16,
+      16, 13, 13, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  5,  9,  3,  6, 10,  8, 10, 12,  3,  6, 10,  6,  8, 10, 10,
+      11, 12,  8,  9, 11, 10, 10, 12, 13, 13, 13,  1,  6, 10,  5,  8,
+      11,  9, 11, 13,  5,  8, 11,  7,  9, 11, 11, 11, 13,  8,  9, 11,
+      10, 10, 12, 13, 13, 14,  6,  9, 12,  8, 11, 13, 11, 13, 15,  8,
+      10, 13, 10, 11, 13, 12, 13, 15, 10, 12, 13, 12, 12, 13, 14, 14,
+      14,  9, 12, 14, 11, 13, 15, 13, 15, 16, 11, 13, 15, 12, 14, 15,
+      14, 15, 16, 13, 14, 15, 14, 14, 15, 15, 16, 16,
+    ], [
+       0,  4, 16,  2,  7, 16, 10, 13, 16,  3,  8, 16,  7, 10, 16, 16,
+      16, 16, 12, 16, 16, 15, 16, 16, 16, 16, 16,  1,  7, 16,  6,  9,
+      16, 10, 16, 16,  7, 12, 16,  9, 13, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16,  9, 16, 16, 11, 13, 16, 16, 16, 16, 12,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  4,  9,  3,  6, 11,  9, 12, 16,  3,  6, 10,  6,  8, 11, 12,
+      13, 16,  8,  9, 12, 10, 11, 13, 16, 16, 16,  1,  6, 10,  5,  8,
+      12, 10, 13, 16,  5,  8, 11,  8,  9, 13, 13, 14, 16,  9, 10, 14,
+      11, 12, 15, 16, 16, 16,  6, 10, 13,  9, 12, 16, 14, 16, 16,  9,
+      12, 14, 11, 13, 16, 16, 16, 16, 12, 14, 16, 14, 16, 16, 16, 16,
+      16, 11, 16, 16, 13, 16, 16, 16, 16, 16, 12, 16, 16, 13, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       0,  4, 16,  2,  8, 16, 10, 16, 16,  3,  9, 16,  8, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  1,  7, 16,  5, 10,
+      16, 16, 16, 16,  7, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 10, 15, 16, 10, 16, 16, 16, 16, 16, 14,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ], [
+    [
+       0,  3,  9,  3,  7, 11, 11, 15, 16,  3,  6, 11,  7,  9, 12, 16,
+      16, 16,  8, 10, 16, 11, 16, 16, 16, 16, 16,  1,  6, 11,  6,  9,
+      15, 16, 16, 16,  5,  8, 16,  9, 11, 16, 16, 16, 16, 10, 16, 16,
+      16, 16, 16, 16, 16, 16,  7, 11, 16, 11, 16, 16, 16, 16, 16, 11,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ], [
+       0,  4, 16,  2,  8, 16, 16, 16, 16,  3, 12, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  1,  7, 16,  5, 12,
+      16, 16, 16, 16,  6, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16,  9, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    ],
+  ],
+];
+
+const RV34_INTER_COEFFS: &[[u8; 32]; 7] = &[
+[
+  1,  2,  4,  4,  5,  5,  6,  7,  7,  7,  8,  8,  8,  9,  9, 10,
+ 10, 10, 10, 11, 11, 11, 11, 12, 11, 11, 11, 13, 14, 15, 16, 16,
+], [
+  1,  2,  3,  5,  5,  6,  6,  7,  7,  8,  9,  9,  9, 10, 10, 10,
+ 11, 11, 12, 12, 12, 12, 13, 13, 12, 12, 13, 14, 16, 16, 16, 16,
+], [
+  1,  2,  3,  4,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10, 11, 12,
+ 12, 12, 13, 13, 13, 14, 14, 15, 14, 14, 16, 16, 16, 16, 16, 16,
+], [
+  1,  2,  3,  4,  5,  6,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
+ 13, 13, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+], [
+  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 13, 14, 15, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+], [
+  1,  2,  3,  4,  5,  6,  7,  8, 10, 10, 11, 11, 13, 12, 12, 13,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+], [
+  1,  2,  3,  4,  5,  6,  7,  8, 10, 10, 10, 11, 14, 13, 15, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16,
+]];
diff --git a/src/codecs/real/rv34dsp.rs b/src/codecs/real/rv34dsp.rs
new file mode 100644 (file)
index 0000000..c8c87fb
--- /dev/null
@@ -0,0 +1,564 @@
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy)]
+pub enum PredType4x4 {
+    Ver,
+    Hor,
+    DC,
+    DiagDownLeft,
+    DiagDownRight,
+    VerRight,
+    HorDown,
+    VerLeft,
+    HorUp,
+    LeftDC,
+    TopDC,
+    DC128,
+    DiagDownLeftNoDown,
+    HorUpNoDown,
+    VerLeftNoDown
+}
+
+#[allow(dead_code)]
+#[derive(Debug,Clone,Copy)]
+pub enum PredType8x8 {
+    DC,
+    Hor,
+    Ver,
+    Plane,
+    LeftDC,
+    TopDC,
+    DC128
+}
+
+pub struct RV34CommonDSP {
+    pub ipred4x4:   [fn(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]); 15],
+    pub ipred8x8:   [fn(buf: &mut [u8], idx: usize, stride: usize); 7],
+    pub ipred16x16: [fn(buf: &mut [u8], idx: usize, stride: usize); 7],
+}
+
+fn row_transform(src: &[i16], dst: &mut [i32]) {
+    for i in 0..4 {
+        let z0 = 13 * ((src[i + 4*0] as i32) + (src[i + 4*2] as i32));
+        let z1 = 13 * ((src[i + 4*0] as i32) - (src[i + 4*2] as i32));
+        let z2 =  7 *  (src[i + 4*1] as i32) - 17 * (src[i + 4*3] as i32);
+        let z3 = 17 *  (src[i + 4*1] as i32) +  7 * (src[i + 4*3] as i32);
+        dst[4 * i + 0] = z0 + z3;
+        dst[4 * i + 1] = z1 + z2;
+        dst[4 * i + 2] = z1 - z2;
+        dst[4 * i + 3] = z0 - z3;
+    }
+}
+
+fn clip8(a: i16) -> u8 {
+    if a < 0 { 0 }
+    else if a > 255 { 255 }
+    else { a as u8 }
+}
+
+#[inline(always)]
+fn mclip8(a: i32) -> u8 {
+    if (a as u32) > 255 { !(a >> 16) as u8 }
+    else { a as u8 }
+}
+
+impl RV34CommonDSP {
+    pub fn new() -> Self {
+        Self {
+            ipred4x4:   IPRED_FUNCS4X4,
+            ipred8x8:   IPRED_FUNCS8X8,
+            ipred16x16: IPRED_FUNCS16X16,
+        }
+    }
+    pub fn add_coeffs(&self, dst: &mut [u8], idx: usize, stride: usize, coeffs: &[i16]) {
+        let out = &mut dst[idx..][..stride * 3 + 4];
+        let mut sidx: usize = 0;
+        for el in out.chunks_mut(stride).take(4) {
+            assert!(el.len() >= 4);
+            el[0] = mclip8((el[0] as i32) + (coeffs[0 + sidx] as i32));
+            el[1] = mclip8((el[1] as i32) + (coeffs[1 + sidx] as i32));
+            el[2] = mclip8((el[2] as i32) + (coeffs[2 + sidx] as i32));
+            el[3] = mclip8((el[3] as i32) + (coeffs[3 + sidx] as i32));
+            sidx += 4;
+        }
+    }
+    pub fn transform(&self, coeffs: &mut [i16]) {
+        let mut tmp: [i32; 16] = [0; 16];
+        row_transform(coeffs, &mut tmp);
+        for i in 0..4 {
+            let z0 = 13*(tmp[4*0+i] +    tmp[4*2+i]) + 0x200;
+            let z1 = 13*(tmp[4*0+i] -    tmp[4*2+i]) + 0x200;
+            let z2 =  7* tmp[4*1+i] - 17*tmp[4*3+i];
+            let z3 = 17* tmp[4*1+i] +  7*tmp[4*3+i];
+            coeffs[i * 4 + 0] = ((z0 + z3) >> 10) as i16;
+            coeffs[i * 4 + 1] = ((z1 + z2) >> 10) as i16;
+            coeffs[i * 4 + 2] = ((z1 - z2) >> 10) as i16;
+            coeffs[i * 4 + 3] = ((z0 - z3) >> 10) as i16;
+        }
+    }
+    pub fn transform_dc(&self, coeffs: &mut [i16]) {
+        let val = (((coeffs[0] as i32) * 13 * 13 + 0x200) >> 10) as i16;
+        for i in 0..16 { coeffs[i] = val; }
+    }
+    pub fn transform16(&self, coeffs: &mut [i16]) {
+        let mut tmp: [i32; 16] = [0; 16];
+        row_transform(coeffs, &mut tmp);
+        for i in 0..4 {
+            let z0 = 39*(tmp[4*0+i] +    tmp[4*2+i]);
+            let z1 = 39*(tmp[4*0+i] -    tmp[4*2+i]);
+            let z2 = 21* tmp[4*1+i] - 51*tmp[4*3+i];
+            let z3 = 51* tmp[4*1+i] + 21*tmp[4*3+i];
+
+            coeffs[i * 4 + 0] = ((z0 + z3) >> 11) as i16;
+            coeffs[i * 4 + 1] = ((z1 + z2) >> 11) as i16;
+            coeffs[i * 4 + 2] = ((z1 - z2) >> 11) as i16;
+            coeffs[i * 4 + 3] = ((z0 - z3) >> 11) as i16;
+        }
+    }
+    pub fn transform16_dc(&self, coeffs: &mut [i16]) {
+        let val = (((coeffs[0] as i32) * 13 * 13 * 3) >> 11) as i16;
+        for i in 0..16 { coeffs[i] = val; }
+    }
+    pub fn weight(&self, dst: &mut [u8], mut didx: usize, dstride: usize,
+              src: &[u8], mut sidx: usize, sstride: usize, ratio1: u32, ratio2: u32,
+              size: usize) {
+        for _ in 0..size {
+            for x in 0..size {
+                dst[didx + x] = (((((dst[didx + x] as u32) * ratio1) >> 9)
+                                + (((src[sidx + x] as u32) * ratio2) >> 9) + 0x10) >> 5) as u8;
+            }
+            didx += dstride;
+            sidx += sstride;
+        }
+    }
+    pub fn avg(&self, dst: &mut [u8], mut didx: usize, dstride: usize,
+               src: &[u8], mut sidx: usize, sstride: usize,
+               size: usize) {
+        for _ in 0..size {
+            for x in 0..size {
+                dst[didx + x] = (((dst[didx + x] as u16) + (src[sidx + x] as u16) + 1) >> 1) as u8;
+            }
+            didx += dstride;
+            sidx += sstride;
+        }
+    }
+}
+
+fn ipred_dc128(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize) {
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = 128; }
+        idx += stride;
+    }
+}
+fn ipred_ver(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize) {
+    let oidx = idx - stride;
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = buf[oidx + x]; }
+        idx += stride;
+    }
+}
+fn ipred_hor(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize) {
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = buf[idx - 1]; }
+        idx += stride;
+    }
+}
+fn ipred_dc(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize, shift: u8) {
+    let mut adc: u16 = 0;
+    for i in 0..bsize { adc += buf[idx - stride + i] as u16; }
+    for i in 0..bsize { adc += buf[idx - 1 + i * stride] as u16; }
+    let dc = ((adc + (1 << (shift - 1))) >> shift) as u8;
+
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = dc; }
+        idx += stride;
+    }
+}
+fn ipred_left_dc(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize, shift: u8) {
+    let mut adc: u16 = 0;
+    for i in 0..bsize { adc += buf[idx - 1 + i * stride] as u16; }
+    let dc = ((adc + (1 << (shift - 1))) >> shift) as u8;
+
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = dc; }
+        idx += stride;
+    }
+}
+fn ipred_top_dc(buf: &mut [u8], mut idx: usize, stride: usize, bsize: usize, shift: u8) {
+    let mut adc: u16 = 0;
+    for i in 0..bsize { adc += buf[idx - stride + i] as u16; }
+    let dc = ((adc + (1 << (shift - 1))) >> shift) as u8;
+
+    for _ in 0..bsize {
+        for x in 0..bsize { buf[idx + x] = dc; }
+        idx += stride;
+    }
+}
+
+fn load_top(dst: &mut [u16], buf: &mut [u8], idx: usize, stride: usize, len: usize) {
+    for i in 0..len { dst[i] = buf[idx - stride + i] as u16; }
+}
+fn load_left(dst: &mut [u16], buf: &mut [u8], idx: usize, stride: usize, len: usize) {
+    for i in 0..len { dst[i] = buf[idx - 1 + i * stride] as u16; }
+}
+
+fn ipred_4x4_ver(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_ver(buf, idx, stride, 4);
+}
+fn ipred_4x4_hor(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_hor(buf, idx, stride, 4);
+}
+fn ipred_4x4_diag_down_left(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    let mut t: [u16; 8] = [0; 8];
+    let mut l: [u16; 8] = [0; 8];
+    load_top(&mut t, buf, idx, stride, 4);
+    for i in 0..4 { t[i + 4] = tr[i] as u16; }
+    load_left(&mut l, buf, idx, stride, 8);
+    let dst = &mut buf[idx..];
+
+    dst[0 + 0 * stride] = ((t[0] + t[2] + 2*t[1] + 2 + l[0] + l[2] + 2*l[1] + 2) >> 3) as u8;
+    let pix = ((t[1] + t[3] + 2*t[2] + 2 + l[1] + l[3] + 2*l[2] + 2) >> 3) as u8;
+    dst[1 + 0 * stride] = pix;
+    dst[0 + 1 * stride] = pix;
+    let pix = ((t[2] + t[4] + 2*t[3] + 2 + l[2] + l[4] + 2*l[3] + 2) >> 3) as u8;
+    dst[2 + 0 * stride] = pix;
+    dst[1 + 1 * stride] = pix;
+    dst[0 + 2 * stride] = pix;
+    let pix = ((t[3] + t[5] + 2*t[4] + 2 + l[3] + l[5] + 2*l[4] + 2) >> 3) as u8;
+    dst[3 + 0 * stride] = pix;
+    dst[2 + 1 * stride] = pix;
+    dst[1 + 2 * stride] = pix;
+    dst[0 + 3 * stride] = pix;
+    let pix = ((t[4] + t[6] + 2*t[5] + 2 + l[4] + l[6] + 2*l[5] + 2) >> 3) as u8;
+    dst[3 + 1 * stride] = pix;
+    dst[2 + 2 * stride] = pix;
+    dst[1 + 3 * stride] = pix;
+    let pix = ((t[5] + t[7] + 2*t[6] + 2 + l[5] + l[7] + 2*l[6] + 2) >> 3) as u8;
+    dst[3 + 2 * stride] = pix;
+    dst[2 + 3 * stride] = pix;
+    dst[3 + 3 * stride] = ((t[6] + t[7] + 1 + l[6] + l[7] + 1) >> 2) as u8;
+}
+fn ipred_4x4_diag_down_left_nodown(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    let mut t: [u16; 8] = [0; 8];
+    let mut l: [u16; 4] = [0; 4];
+    load_top(&mut t, buf, idx, stride, 4);
+    for i in 0..4 { t[i + 4] = tr[i] as u16; }
+    load_left(&mut l, buf, idx, stride, 4);
+    let dst = &mut buf[idx..];
+
+    dst[0 + 0 * stride] = ((t[0] + t[2] + 2*t[1] + 2 + l[0] + l[2] + 2*l[1] + 2) >> 3) as u8;
+    let pix = ((t[1] + t[3] + 2*t[2] + 2 + l[1] + l[3] + 2*l[2] + 2) >> 3) as u8;
+    dst[1 + 0 * stride] = pix;
+    dst[0 + 1 * stride] = pix;
+    let pix = ((t[2] + t[4] + 2*t[3] + 2 + l[2] + 3*l[3] + 2) >> 3) as u8;
+    dst[2 + 0 * stride] = pix;
+    dst[1 + 1 * stride] = pix;
+    dst[0 + 2 * stride] = pix;
+    let pix = ((t[3] + t[5] + 2*t[4] + 2 + l[3]*4 + 2) >> 3) as u8;
+    dst[3 + 0 * stride] = pix;
+    dst[2 + 1 * stride] = pix;
+    dst[1 + 2 * stride] = pix;
+    dst[0 + 3 * stride] = pix;
+    let pix = ((t[4] + t[6] + 2*t[5] + 2 + l[3]*4 + 2) >> 3) as u8;
+    dst[3 + 1 * stride] = pix;
+    dst[2 + 2 * stride] = pix;
+    dst[1 + 3 * stride] = pix;
+    let pix = ((t[5] + t[7] + 2*t[6] + 2 + l[3]*4 + 2) >> 3) as u8;
+    dst[3 + 2 * stride] = pix;
+    dst[2 + 3 * stride] = pix;
+    dst[3 + 3 * stride] = ((t[6] + t[7] + 1 + 2*l[3] + 1) >> 2) as u8;
+}
+fn ipred_4x4_diag_down_right(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    let mut t: [u16; 5] = [0; 5];
+    let mut l: [u16; 5] = [0; 5];
+    load_top(&mut t, buf, idx - 1, stride, 5);
+    load_left(&mut l, buf, idx - stride, stride, 5);
+    let dst = &mut buf[idx..];
+
+    for j in 0..4 {
+        for i in 0..j {
+            dst[i + j * stride] = ((l[j - i - 1] + 2 * l[j - i] + l[j - i + 1] + 2) >> 2) as u8;
+        }
+        dst[j + j * stride] = ((l[1] + 2 * l[0] + t[1] + 2) >> 2) as u8;
+        for i in (j+1)..4 {
+            dst[i + j * stride] = ((t[i - j - 1] + 2 * t[i - j] + t[i - j + 1] + 2) >> 2) as u8;
+        }
+    }
+}
+fn ipred_4x4_ver_right(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    let mut t: [u16; 5] = [0; 5];
+    let mut l: [u16; 5] = [0; 5];
+    load_top(&mut t, buf, idx - 1, stride, 5);
+    load_left(&mut l, buf, idx - stride, stride, 5);
+    let dst = &mut buf[idx..];
+
+    for j in 0..4 {
+        for i in 0..4 {
+            let zvr = ((2 * i) as i8) - (j as i8);
+            let pix;
+            if zvr >= 0 {
+                if (zvr & 1) == 0 {
+                    pix = (t[i - (j >> 1)] + t[i - (j >> 1) + 1] + 1) >> 1;
+                } else {
+                    pix = (t[i - (j >> 1) - 1] + 2 * t[i - (j >> 1)] + t[i - (j >> 1) + 1] + 2) >> 2;
+                }
+            } else {
+                if zvr == -1 {
+                    pix = (l[1] + 2 * l[0] + t[1] + 2) >> 2;
+                } else {
+                    pix = (l[j] + 2 * l[j - 1] + l[j - 2] + 2) >> 2;
+                }
+            }
+            dst[i + j * stride] = pix as u8;
+        }
+    }
+}
+fn ipred_4x4_ver_left_common(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8], no_down: bool) {
+    let mut t: [u16; 8] = [0; 8];
+    let mut l: [u16; 5] = [0; 5];
+    load_top(&mut t, buf, idx, stride, 4);
+    for i in 0..4 { t[i + 4] = tr[i] as u16; }
+    load_left(&mut l, buf, idx, stride, 4);
+    l[4] = if no_down { l[3] } else { buf[idx - 1 + 4 * stride] as u16 };
+    let dst = &mut buf[idx..];
+
+    dst[0 + 0 * stride] = ((2*t[0] + 2*t[1] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
+    let pix = ((t[1] + t[2] + 1) >> 1) as u8;
+    dst[1 + 0 * stride] = pix;
+    dst[0 + 2 * stride] = pix;
+    let pix = ((t[2] + t[3] + 1) >> 1) as u8;
+    dst[2 + 0 * stride] = pix;
+    dst[1 + 2 * stride] = pix;
+    let pix = ((t[3] + t[4] + 1) >> 1) as u8;
+    dst[3 + 0 * stride] = pix;
+    dst[2 + 2 * stride] = pix;
+    dst[3 + 2 * stride] = ((t[4] + t[5] + 1) >> 1) as u8;
+    dst[0 + 1 * stride] = ((t[0] + 2*t[1] + t[2] + l[2] + 2*l[3] + l[4] + 4) >> 3) as u8;
+    let pix = ((t[1] + 2*t[2] + t[3] + 2) >> 2) as u8;
+    dst[1 + 1 * stride] = pix;
+    dst[0 + 3 * stride] = pix;
+    let pix = ((t[2] + 2*t[3] + t[4] + 2) >> 2) as u8;
+    dst[2 + 1 * stride] = pix;
+    dst[1 + 3 * stride] = pix;
+    let pix = ((t[3] + 2*t[4] + t[5] + 2) >> 2) as u8;
+    dst[3 + 1 * stride] = pix;
+    dst[2 + 3 * stride] = pix;
+    dst[3 + 3 * stride] = ((t[4] + 2*t[5] + t[6] + 2) >> 2) as u8;
+}
+
+fn ipred_4x4_ver_left(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    ipred_4x4_ver_left_common(buf, idx, stride, tr, false);
+}
+fn ipred_4x4_ver_left_nodown(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    ipred_4x4_ver_left_common(buf, idx, stride, tr, true);
+}
+fn ipred_4x4_hor_down(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    let mut t: [u16; 5] = [0; 5];
+    let mut l: [u16; 5] = [0; 5];
+    load_top(&mut t, buf, idx - 1, stride, 5);
+    load_left(&mut l, buf, idx - stride, stride, 5);
+    let dst = &mut buf[idx..];
+
+    for j in 0..4 {
+        for i in 0..4 {
+            let zhd = ((2 * j) as i8) - (i as i8);
+            let pix;
+            if zhd >= 0 {
+                if (zhd & 1) == 0 {
+                    pix = (l[j - (i >> 1)] + l[j - (i >> 1) + 1] + 1) >> 1;
+                } else {
+                    pix = (l[j - (i >> 1) - 1] + 2 * l[j - (i >> 1)] + l[j - (i >> 1) + 1] + 2) >> 2;
+                }
+            } else {
+                if zhd == -1 {
+                    pix = (l[1] + 2 * l[0] + t[1] + 2) >> 2;
+                } else {
+                    pix = (t[i - 2] + 2 * t[i - 1] + t[i] + 2) >> 2;
+                }
+            }
+            dst[i + j * stride] = pix as u8;
+        }
+    }
+}
+fn ipred_4x4_hor_up(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    let mut t: [u16; 8] = [0; 8];
+    let mut l: [u16; 8] = [0; 8];
+    load_top(&mut t, buf, idx, stride, 4);
+    for i in 0..4 { t[i + 4] = tr[i] as u16; }
+    load_left(&mut l, buf, idx, stride, 8);
+    let dst = &mut buf[idx..];
+
+    dst[0 + 0 * stride] = ((t[1] + 2*t[2] + t[3] + 2*l[0] + 2*l[1] + 4) >> 3) as u8;
+    dst[1 + 0 * stride] = ((t[2] + 2*t[3] + t[4] + l[0] + 2*l[1] + l[2] + 4) >> 3) as u8;
+    let pix = ((t[3] + 2*t[4] + t[5] + 2*l[1] + 2*l[2] + 4) >> 3) as u8;
+    dst[2 + 0 * stride] = pix;
+    dst[0 + 1 * stride] = pix;
+    let pix = ((t[4] + 2*t[5] + t[6] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
+    dst[3 + 0 * stride] = pix;
+    dst[1 + 1 * stride] = pix;
+    let pix = ((t[5] + 2*t[6] + t[7] + 2*l[2] + 2*l[3] + 4) >> 3) as u8;
+    dst[2 + 1 * stride] = pix;
+    dst[0 + 2 * stride] = pix;
+    let pix = ((t[6] + 3*t[7] + l[2] + 3*l[3] + 4) >> 3) as u8;
+    dst[3 + 1 * stride] = pix;
+    dst[1 + 2 * stride] = pix;
+    let pix = ((l[3] + 2*l[4] + l[5] + 2) >> 2) as u8;
+    dst[3 + 2 * stride] = pix;
+    dst[1 + 3 * stride] = pix;
+    let pix = ((t[6] + t[7] + l[3] + l[4] + 2) >> 2) as u8;
+    dst[0 + 3 * stride] = pix;
+    dst[2 + 2 * stride] = pix;
+    dst[2 + 3 * stride] = ((l[4] + l[5] + 1) >> 1) as u8;
+    dst[3 + 3 * stride] = ((l[4] + 2*l[5] + l[6] + 2) >> 2) as u8;
+}
+fn ipred_4x4_hor_up_nodown(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]) {
+    let mut t: [u16; 8] = [0; 8];
+    let mut l: [u16; 4] = [0; 4];
+    load_top(&mut t, buf, idx, stride, 4);
+    for i in 0..4 { t[i + 4] = tr[i] as u16; }
+    load_left(&mut l, buf, idx, stride, 4);
+    let dst = &mut buf[idx..];
+
+    dst[0 + 0 * stride] = ((t[1] + 2*t[2] + t[3] + 2*l[0] + 2*l[1] + 4) >> 3) as u8;
+    dst[1 + 0 * stride] = ((t[2] + 2*t[3] + t[4] + l[0] + 2*l[1] + l[2] + 4) >> 3) as u8;
+    let pix = ((t[3] + 2*t[4] + t[5] + 2*l[1] + 2*l[2] + 4) >> 3) as u8;
+    dst[2 + 0 * stride] = pix;
+    dst[0 + 1 * stride] = pix;
+    let pix = ((t[4] + 2*t[5] + t[6] + l[1] + 2*l[2] + l[3] + 4) >> 3) as u8;
+    dst[3 + 0 * stride] = pix;
+    dst[1 + 1 * stride] = pix;
+    let pix = ((t[5] + 2*t[6] + t[7] + 2*l[2] + 2*l[3] + 4) >> 3) as u8;
+    dst[2 + 1 * stride] = pix;
+    dst[0 + 2 * stride] = pix;
+    let pix = ((t[6] + 3*t[7] + l[2] + 3*l[3] + 4) >> 3) as u8;
+    dst[3 + 1 * stride] = pix;
+    dst[1 + 2 * stride] = pix;
+    dst[3 + 2 * stride] = l[3] as u8;
+    dst[1 + 3 * stride] = l[3] as u8;
+    let pix = ((t[6] + t[7] + 2*l[3] + 2) >> 2) as u8;
+    dst[0 + 3 * stride] = pix;
+    dst[2 + 2 * stride] = pix;
+    dst[2 + 3 * stride] = l[3] as u8;
+    dst[3 + 3 * stride] = l[3] as u8;
+}
+fn ipred_4x4_dc(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_dc(buf, idx, stride, 4, 3);
+}
+fn ipred_4x4_left_dc(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_left_dc(buf, idx, stride, 4, 2);
+}
+fn ipred_4x4_top_dc(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_top_dc(buf, idx, stride, 4, 2);
+}
+fn ipred_4x4_dc128(buf: &mut [u8], idx: usize, stride: usize, _tr: &[u8]) {
+    ipred_dc128(buf, idx, stride, 4);
+}
+
+fn ipred_8x8_ver(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_ver(buf, idx, stride, 8);
+}
+fn ipred_8x8_hor(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_hor(buf, idx, stride, 8);
+}
+fn ipred_8x8_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_dc(buf, idx, stride, 8, 4);
+}
+fn ipred_8x8_left_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_left_dc(buf, idx, stride, 8, 3);
+}
+fn ipred_8x8_top_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_top_dc(buf, idx, stride, 8, 3);
+}
+fn ipred_8x8_dc128(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_dc128(buf, idx, stride, 8);
+}
+fn ipred_8x8_plane(_buf: &mut [u8], _idx: usize, _stride: usize) {
+    unreachable!();
+/*    let mut h: i16 = 0;
+    let mut v: i16 = 0;
+    for i in 0..4 {
+        let i1 = (i + 1) as i16;
+        h += i1 * ((buf[idx + (4 + i)          - stride] as i16) - (buf[idx + (2 - i)          - stride] as i16));
+        v += i1 * ((buf[idx + (4 + i) * stride - 1]      as i16) - (buf[idx + (2 - i) * stride - 1] as i16));
+    }
+    let a = 16 * ((buf[idx - 1 + 7 * stride] as i16) + (buf[idx + 7 - stride] as i16));
+    let b = (17 * h + 16) >> 5;
+    let c = (17 * v + 16) >> 5;
+    for y in 0..8 {
+        let j3 = (y as i16) - 3;
+        for x in 0..8 {
+            let i3 = (x as i16) - 3;
+            buf[idx + x] = clip8((a + b * i3 + c * j3 + 16) >> 5);
+        }
+        idx += stride;
+    }*/
+}
+
+fn ipred_16x16_ver(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_ver(buf, idx, stride, 16);
+}
+fn ipred_16x16_hor(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_hor(buf, idx, stride, 16);
+}
+fn ipred_16x16_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_dc(buf, idx, stride, 16, 5);
+}
+fn ipred_16x16_left_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_left_dc(buf, idx, stride, 16, 4);
+}
+fn ipred_16x16_top_dc(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_top_dc(buf, idx, stride, 16, 4);
+}
+fn ipred_16x16_dc128(buf: &mut [u8], idx: usize, stride: usize) {
+    ipred_dc128(buf, idx, stride, 16);
+}
+fn ipred_16x16_plane(buf: &mut [u8], mut idx: usize, stride: usize) {
+    let     idx0 = idx + 7 - stride;
+    let mut idx1 = idx + 8*stride - 1;
+    let mut idx2 = idx1 - 2*stride;
+
+    let mut h = (buf[idx0 + 1] as i16) - (buf[idx0 - 1] as i16);
+    let mut v = (buf[idx1 + 0] as i16) - (buf[idx2 + 0] as i16);
+
+    for k in 2..9 {
+        idx1 += stride;
+        idx2 -= stride;
+        h += (k as i16) * ((buf[idx0 + k] as i16) - (buf[idx0 - k] as i16));
+        v += (k as i16) * ((buf[idx1 + 0] as i16) - (buf[idx2 + 0] as i16));
+    }
+    h = (h + (h >> 2)) >> 4;
+    v = (v + (v >> 2)) >> 4;
+
+    let mut a = 16 * ((buf[idx1 + 0] as i16) + (buf[idx2 + 16] as i16) + 1) - 7 * (v + h);
+
+    for _ in 0..16 {
+        let mut b = a;
+        a += v;
+
+        for x in 0..4 {
+            buf[idx + x * 4 + 0] = clip8((b      ) >> 5);
+            buf[idx + x * 4 + 1] = clip8((b +   h) >> 5);
+            buf[idx + x * 4 + 2] = clip8((b + 2*h) >> 5);
+            buf[idx + x * 4 + 3] = clip8((b + 3*h) >> 5);
+            b += h * 4;
+        }
+        idx += stride;
+    }
+}
+
+const IPRED_FUNCS4X4: [fn(buf: &mut [u8], idx: usize, stride: usize, tr: &[u8]); 15] = [
+    ipred_4x4_ver, ipred_4x4_hor, ipred_4x4_dc,
+    ipred_4x4_diag_down_left, ipred_4x4_diag_down_right,
+    ipred_4x4_ver_right, ipred_4x4_hor_down, ipred_4x4_ver_left, ipred_4x4_hor_up,
+    ipred_4x4_left_dc, ipred_4x4_top_dc, ipred_4x4_dc128,
+    ipred_4x4_diag_down_left_nodown, ipred_4x4_hor_up_nodown, ipred_4x4_ver_left_nodown
+];
+
+const IPRED_FUNCS8X8: [fn(buf: &mut [u8], idx: usize, stride: usize); 7] = [
+    ipred_8x8_dc, ipred_8x8_hor, ipred_8x8_ver, ipred_8x8_plane,
+    ipred_8x8_left_dc, ipred_8x8_top_dc, ipred_8x8_dc128
+];
+
+const IPRED_FUNCS16X16: [fn(buf: &mut [u8], idx: usize, stride: usize); 7] = [
+    ipred_16x16_dc, ipred_16x16_hor, ipred_16x16_ver, ipred_16x16_plane,
+    ipred_16x16_left_dc, ipred_16x16_top_dc, ipred_16x16_dc128
+];
diff --git a/src/codecs/real/rv40.rs b/src/codecs/real/rv40.rs
new file mode 100644 (file)
index 0000000..a9619d4
--- /dev/null
@@ -0,0 +1,1070 @@
+use formats;
+use io::bitreader::*;
+use io::codebook::*;
+use io::intcode::*;
+use codecs::*;
+use super::rv3040::*;
+use super::rv40dsp::*;
+
+struct AICCodeReader8 {
+    lengths: &'static [u8],
+    codes:   &'static [u8],
+}
+
+impl CodebookDescReader<i8> for AICCodeReader8 {
+    fn bits(&mut self, idx: usize) -> u8    { self.lengths[idx] }
+    fn code(&mut self, idx: usize) -> u32   { self.codes[idx] as u32 }
+    fn sym (&mut self, idx: usize) -> i8    { idx as i8 }
+    fn len (&mut self)             -> usize { self.lengths.len() }
+}
+
+struct AICCodeReader16 {
+    lengths: &'static [u8],
+    codes:   &'static [u16],
+}
+
+impl CodebookDescReader<i8> for AICCodeReader16 {
+    fn bits(&mut self, idx: usize) -> u8    { self.lengths[idx] }
+    fn code(&mut self, idx: usize) -> u32   { self.codes[idx] as u32 }
+    fn sym (&mut self, idx: usize) -> i8    { idx as i8 }
+    fn len (&mut self)             -> usize { self.lengths.len() }
+}
+
+struct TypeCodeReader {
+    lengths: &'static [u8],
+    codes:   &'static [u8],
+    syms:    &'static [MBType],
+}
+
+impl CodebookDescReader<MBType> for TypeCodeReader {
+    fn bits(&mut self, idx: usize) -> u8    { self.lengths[idx] }
+    fn code(&mut self, idx: usize) -> u32   { self.codes[idx] as u32 }
+    fn sym (&mut self, idx: usize) -> MBType{ self.syms[idx] }
+    fn len (&mut self)             -> usize { self.lengths.len() }
+}
+
+struct RealVideo40BR {
+    width:          usize,
+    height:         usize,
+    aic_top_cb:     Codebook<i8>,
+    aic_mode1_cb:   Vec<Codebook<i8>>,
+    aic_mode2_cb:   Vec<Codebook<i8>>,
+    ptype_cb:       Vec<Codebook<MBType>>,
+    btype_cb:       Vec<Codebook<MBType>>,
+    had_skip_run:   bool,
+}
+
+impl RealVideo40BR {
+    fn new() -> Self {
+        let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_TOP_BITS, codes: &RV40_AIC_TOP_CODES };
+        let aic_top_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+
+        let mut aic_mode1_cb: Vec<Codebook<i8>> = Vec::with_capacity(RV40_AIC_MODE1_BITS.len());
+        for i in 0..RV40_AIC_MODE1_BITS.len() {
+            if (i % 10) != 9 {
+                let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_MODE1_BITS[i], codes: &RV40_AIC_MODE1_CODES[i] };
+                let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+                aic_mode1_cb.push(cb);
+            } else {
+                let mut coderead = AICCodeReader8{ lengths: &RV40_AIC_MODE1_BITS_DUMMY, codes: &RV40_AIC_MODE1_CODES_DUMMY };
+                let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+                aic_mode1_cb.push(cb);
+            }
+        }
+
+        let mut aic_mode2_cb: Vec<Codebook<i8>> = Vec::with_capacity(RV40_AIC_MODE2_BITS.len());
+        for i in 0..RV40_AIC_MODE2_BITS.len() {
+            let mut coderead = AICCodeReader16{ lengths: &RV40_AIC_MODE2_BITS[i], codes: &RV40_AIC_MODE2_CODES[i] };
+            let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            aic_mode2_cb.push(cb);
+        }
+
+        let mut ptype_cb: Vec<Codebook<MBType>> = Vec::with_capacity(RV40_PTYPE_BITS.len());
+        for i in 0..RV40_PTYPE_BITS.len() {
+            let mut coderead = TypeCodeReader{ lengths: &RV40_PTYPE_BITS[i], codes: &RV40_PTYPE_CODES[i], syms: RV40_PTYPE_SYMS };
+            let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            ptype_cb.push(cb);
+        }
+
+        let mut btype_cb: Vec<Codebook<MBType>> = Vec::with_capacity(RV40_BTYPE_BITS.len());
+        for i in 0..RV40_BTYPE_BITS.len() {
+            let mut coderead = TypeCodeReader{ lengths: &RV40_BTYPE_BITS[i], codes: &RV40_BTYPE_CODES[i], syms: RV40_BTYPE_SYMS };
+            let cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap();
+            btype_cb.push(cb);
+        }
+
+        RealVideo40BR {
+            width:          0,
+            height:         0,
+            aic_top_cb:     aic_top_cb,
+            aic_mode1_cb:   aic_mode1_cb,
+            aic_mode2_cb:   aic_mode2_cb,
+            ptype_cb:       ptype_cb,
+            btype_cb:       btype_cb,
+            had_skip_run:   false,
+        }
+    }
+    fn predict_b_mv_component(&self, sstate: &SState, mvi: &MVInfo, mbinfo: &Vec<RV34MBInfo>, mbtype: MBType, fwd: bool) -> MV {
+        let mut pred_mvs: [MV; 3] = [ZERO_MV; 3];
+        let mut mv_count: usize = 0;
+        let mb_x = sstate.mb_x;
+        let mb_y = sstate.mb_y;
+        let mb_stride = sstate.mb_w;
+        let mb_idx = mb_x + mb_y * mb_stride;
+
+        if !mbtype.has_mv_dir(fwd) {
+            return ZERO_MV;
+        }
+
+        if sstate.has_left && mbinfo[mb_idx - 1].mbtype.has_mv_dir(fwd) {
+            pred_mvs[mv_count] = mvi.get_mv(mb_x - 1, mb_y, 0, 0, fwd);
+            mv_count += 1;
+        }
+        if !sstate.has_top {
+            return pred_mvs[0];
+        }
+        if mbinfo[mb_idx - mb_stride].mbtype.has_mv_dir(fwd) {
+            pred_mvs[mv_count] = mvi.get_mv(mb_x, mb_y - 1, 0, 0, fwd);
+            mv_count += 1;
+        }
+        if sstate.has_tr {
+            if mbinfo[mb_idx - mb_stride + 1].mbtype.has_mv_dir(fwd) {
+                pred_mvs[mv_count] = mvi.get_mv(mb_x + 1, mb_y - 1, 0, 0, fwd);
+                mv_count += 1;
+            }
+        } else {
+            if sstate.has_tl && mbinfo[mb_idx - mb_stride - 1].mbtype.has_mv_dir(fwd) {
+                pred_mvs[mv_count] = mvi.get_mv(mb_x - 1, mb_y - 1, 0, 0, fwd);
+                mv_count += 1;
+            }
+        }
+
+        match mv_count {
+            3 => MV::pred(pred_mvs[0], pred_mvs[1], pred_mvs[2]),
+            2 => { let sum_mv = pred_mvs[0] + pred_mvs[1]; MV { x: sum_mv.x / 2, y: sum_mv.y / 2 } },
+            1 => pred_mvs[0],
+            _ => ZERO_MV,
+        }
+    }
+}
+
+fn get_dimension(br: &mut BitReader, tab: &'static [i16]) -> DecoderResult<usize> {
+    let t = br.read(3)? as usize;
+    if tab[t] > 0 { return Ok(tab[t] as usize); }
+    if tab[t] < 0 {
+        let idx = (-tab[t] as usize) + (br.read(1)? as usize);
+        if tab[idx] != 0 { return Ok(tab[idx] as usize); }
+    }
+    let mut size: usize = 0;
+    loop {
+        let t = br.read(8)? as usize;
+        size += t << 2;
+        if t != 255 { break; }
+    }
+    Ok(size)
+}
+
+impl RV34BitstreamDecoder for RealVideo40BR {
+    fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader> {
+        if br.read(1)? != 0 { return Err(DecoderError::InvalidData); }
+        let ft_idx              = br.read(2)?;
+        let ftype = match ft_idx {
+                0|1 => FrameType::I,
+                2   => FrameType::P,
+                _   => FrameType::B,
+            };
+        let q                   = br.read(5)? as u8;
+        if br.read(2)? != 0 { return Err(DecoderError::InvalidData); }
+        let set_idx             = br.read(2)? as usize;
+        let deblock             = !br.read_bool()?;
+        let pts                 = br.read(13)? as u16;
+        let w;
+        let h;
+        if (ftype == FrameType::I) || !br.read_bool()? {
+            w = get_dimension(br, &RV40_STANDARD_WIDTHS)?;
+            h = get_dimension(br, &RV40_STANDARD_HEIGHTS)?;
+        } else {
+            w = old_w;
+            h = old_h;
+        }
+        let start               = br.read(get_slice_start_offset_bits(w, h))? as usize;
+//println!(" type {:?} q {} set {} pts {} {}x{} start {} @ {}", ftype, q, set_idx, pts, w, h, start, br.tell());
+
+        self.had_skip_run = false;
+
+        Ok(RV34SliceHeader{ ftype: ftype, quant: q, deblock: deblock, pts: pts, width: w, height: h, start: start, end: 0, set_idx: set_idx })
+    }
+    fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], mut pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()> {
+        let start;
+//println!(" @ {}", br.tell());
+        if has_top {
+            start = 0;
+        } else {
+            let code = br.read_cb(&self.aic_top_cb)?;
+            types[pos + 0] = (code >> 2) & 2;
+            types[pos + 1] = (code >> 1) & 2;
+            types[pos + 2] = (code >> 0) & 2;
+            types[pos + 3] = (code << 1) & 2;
+//println!("  first line {} {} {} {} @ {}", types[pos +0],types[pos+1],types[pos+2],types[pos+3],br.tell());
+            pos += tstride;
+            start = 1;
+        }
+        for _ in start..4 {
+            let mut x: usize = 0;
+            while x < 4 {
+                let tr = types[pos + x - tstride + 1];
+                let t  = types[pos + x - tstride];
+                let l  = types[pos + x - 1];
+//println!(" x = {} ctx {} {} {} @ {}", x, l, t, tr, br.tell());
+                let ctx = if x < 3 { ((tr & 0xF) as u16) + (((t as u16) & 0xF) << 4) + (((l as u16) & 0xF) << 8) } else { 0xFFF };
+                let res = RV40_AIC_PATTERNS.iter().position(|&x| x == ctx);
+                if let Some(idx) = res {
+                    let code = br.read_cb(&self.aic_mode2_cb[idx])?;
+                    types[pos + x + 0] = code / 9;
+                    types[pos + x + 1] = code % 9;
+//println!("   -> {} {}", types[pos + x + 0], types[pos + x + 1]);
+                    x += 2;
+                } else {
+                    if (t != -1) && (l != -1) {
+                        let idx = (t as usize) + (l as usize) * 10;
+                        types[pos + x] = br.read_cb(&self.aic_mode1_cb[idx])?;
+                    } else {
+                        match l {
+                            -1 if t < 2 => { types[pos + x] =  (br.read(1)? as i8) ^ 1; },
+                             0 | 2      => { types[pos + x] = ((br.read(1)? as i8) ^ 1) << 1; },
+                            _           => { types[pos + x] = 0; },
+                        };
+                    }
+//println!("   -> {}", types[pos + x]);
+                    x += 1;
+                }
+            }
+            pos += tstride;
+        }
+        Ok(())
+    }
+    fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype_ref: MBType) -> DecoderResult<MBInfo> {
+        let skip_run = if self.had_skip_run { 0 } else { br.read_code(UintCodeType::Gamma)? as usize };
+        if skip_run > 0 {
+            self.had_skip_run = true;
+            return Ok(MBInfo { mbtype: MBType::MBSkip, skip_run: skip_run - 1, dquant: false })
+        }
+        self.had_skip_run = false;
+        let mut mbtype;
+        let idx;
+        if ftype == FrameType::P {
+            idx = match mbtype_ref {
+                    MBType::MBIntra     => 0,
+                    MBType::MBIntra16   => 1,
+                    MBType::MBP16x16    => 2,
+                    MBType::MBP8x8      => 3,
+                    MBType::MBP16x8     => 4,
+                    MBType::MBP8x16     => 5,
+                    MBType::MBP16x16Mix => 6,
+                    _                   => unreachable!(),
+                };
+            mbtype = br.read_cb(&self.ptype_cb[idx])?;
+        } else {
+            idx = match mbtype_ref {
+                    MBType::MBIntra     => 0,
+                    MBType::MBIntra16   => 1,
+                    MBType::MBForward   => 2,
+                    MBType::MBBackward  => 3,
+                    MBType::MBBidir     => 4,
+                    MBType::MBDirect    => 5,
+                    _                   => 0,
+                };
+            mbtype = br.read_cb(&self.btype_cb[idx])?;
+        }
+        let dquant = mbtype == MBType::Invalid;
+        if dquant {
+            mbtype = if ftype == FrameType::P { br.read_cb(&self.ptype_cb[idx])? }
+                     else { br.read_cb(&self.btype_cb[idx])? };
+        }
+        Ok(MBInfo { mbtype: mbtype, skip_run: 0, dquant: dquant })
+    }
+    fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &Vec<RV34MBInfo>) -> (MV, MV) {
+        let mut mv_f = self.predict_b_mv_component(sstate, mvi, mbinfo, mbtype, true);
+        let mut mv_b = self.predict_b_mv_component(sstate, mvi, mbinfo, mbtype, false);
+
+        match mbtype {
+            MBType::MBForward   => { mv_f += mvs[0]; },
+            MBType::MBBackward  => { mv_b += mvs[0]; },
+            MBType::MBBidir     => {
+                    mv_f += mvs[0];
+                    mv_b += mvs[1];
+                },
+            _ => {},
+        };
+
+        (mv_f, mv_b)
+    }
+    fn quant_dc(&self, is_intra: bool, q: u8) -> u8 { RV40_QUANT_DC[if is_intra { 0 } else { 1 }][q as usize] }
+}
+
+struct RealVideo40Decoder {
+    bd:         RealVideo40BR,
+    info:       Rc<NACodecInfo>,
+    dec:        RV34Decoder,
+}
+
+impl RealVideo40Decoder {
+    fn new() -> Self {
+        RealVideo40Decoder{
+            bd:         RealVideo40BR::new(),
+            info:       Rc::new(DUMMY_CODEC_INFO),
+            dec:        RV34Decoder::new(false, Box::new(RV40DSP::new())),
+        }
+    }
+}
+
+impl NADecoder for RealVideo40Decoder {
+    fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
+        if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
+            let fmt = formats::YUV420_FORMAT;
+            let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
+            self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+
+            let edata = info.get_extradata().unwrap();
+            let src: &[u8] = &edata;
+
+{
+println!("edata:");
+for i in 0..src.len() { print!(" {:02X}", src[i]); } println!("");
+}
+            if src.len() < 2 { return Err(DecoderError::InvalidData); }
+
+            self.bd.width  = vinfo.get_width();
+            self.bd.height = vinfo.get_height();
+            Ok(())
+        } else {
+println!("???");
+            Err(DecoderError::InvalidData)
+        }
+    }
+    fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
+        let src = pkt.get_buffer();
+
+//println!(" decode frame size {}, {} slices", src.len(), src[0]+1);
+
+        let (bufinfo, ftype, ts) = self.dec.parse_frame(src.as_slice(), &mut self.bd)?;
+
+        let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
+        frm.set_keyframe(ftype == FrameType::I);
+        frm.set_frame_type(ftype);
+        frm.set_pts(Some(ts));
+        Ok(Rc::new(RefCell::new(frm)))
+    }
+}
+
+pub fn get_decoder() -> Box<NADecoder> {
+    Box::new(RealVideo40Decoder::new())
+}
+
+#[cfg(test)]
+mod test {
+    use test::dec_video::test_file_decoding;
+    #[test]
+    fn test_rv40() {
+//         test_file_decoding("realmedia", "assets/RV/rv40_ralf.rmvb", Some(1000), true, false, /*None*/Some("rv40"));
+         test_file_decoding("realmedia", "assets/RV/rv40_weighted_mc.rmvb", Some(400), true, false, None/*Some("rv40")*/);
+//         test_file_decoding("realmedia", "assets/RV/rv40_weighted_mc_2.rmvb", Some(1000), true, false, /*None*/Some("rv40"));
+panic!("end");
+    }
+}
+
+const RV40_STANDARD_WIDTHS:  [i16;  8] = [ 160, 172, 240, 320, 352, 640, 704, 0 ];
+const RV40_STANDARD_HEIGHTS: [i16; 12] = [ 120, 132, 144, 240, 288, 480, -8, -10, 180, 360, 576, 0 ];
+
+const RV40_QUANT_DC: [[u8; 32]; 2] = [
+  [
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 22, 22, 22, 22
+  ], [
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+   16, 17, 18, 19, 20, 20, 21, 21, 22, 23, 23, 23, 24, 24, 24, 24
+  ]
+];
+
+const RV40_AIC_PATTERNS: [u16; 20] = [
+    0x000, 0x100, 0x200,
+    0x011, 0x111, 0x211, 0x511, 0x611,
+    0x022, 0x122, 0x222, 0x722,
+    0x272, 0x227,
+    0x822, 0x282, 0x228,
+    0x112, 0x116, 0x221
+];
+
+const RV40_AIC_TOP_CODES: [u8; 16] = [
+    0x01, 0x05, 0x01, 0x00, 0x03, 0x3D, 0x1D, 0x02,
+    0x04, 0x3C, 0x3F, 0x1C, 0x0D, 0x3E, 0x0C, 0x01
+];
+const RV40_AIC_TOP_BITS: [u8; 16] = [
+    1, 4, 5, 5, 5, 7, 6, 5, 4, 7, 7, 6, 5, 7, 5, 3
+];
+
+const RV40_AIC_MODE1_CODES_DUMMY: [u8; 1] = [ 0 ];
+const RV40_AIC_MODE1_BITS_DUMMY: [u8; 1] = [ 1 ];
+
+const RV40_AIC_MODE1_CODES: [[u8; 9]; 90] = [
+  [ 0x01, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x10, 0x05 ],
+  [ 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20 ],
+  [ 0x01, 0x01, 0x01, 0x11, 0x09, 0x10, 0x05, 0x00, 0x03 ],
+  [ 0x01, 0x01, 0x00, 0x03, 0x21, 0x05, 0x09, 0x20, 0x11 ],
+  [ 0x01, 0x09, 0x00, 0x29, 0x08, 0x15, 0x03, 0x0B, 0x28 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02 ],
+  [ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x01, 0x09, 0x08 ],
+  [ 0x01, 0x01, 0x01, 0x09, 0x01, 0x08, 0x00, 0x03, 0x05 ],
+  [ 0x01, 0x01, 0x01, 0x00, 0x05, 0x11, 0x09, 0x10, 0x03 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x01, 0x01, 0x05, 0x01, 0x00, 0x03, 0x09, 0x08 ],
+  [ 0x09, 0x01, 0x01, 0x05, 0x11, 0x00, 0x03, 0x21, 0x20 ],
+  [ 0x01, 0x01, 0x01, 0x0D, 0x05, 0x04, 0x00, 0x07, 0x0C ],
+  [ 0x01, 0x01, 0x00, 0x05, 0x11, 0x03, 0x09, 0x21, 0x20 ],
+  [ 0x05, 0x01, 0x01, 0x11, 0x00, 0x09, 0x03, 0x21, 0x20 ],
+  [ 0x09, 0x01, 0x01, 0x00, 0x05, 0x01, 0x03, 0x11, 0x10 ],
+  [ 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x02 ],
+  [ 0x01, 0x01, 0x01, 0x09, 0x00, 0x05, 0x01, 0x03, 0x08 ],
+  [ 0x01, 0x01, 0x01, 0x09, 0x11, 0x05, 0x00, 0x10, 0x03 ],
+  [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x00, 0x01, 0x09, 0x08, 0x15, 0x14, 0x0B, 0x03 ],
+  [ 0x0D, 0x01, 0x01, 0x05, 0x0C, 0x04, 0x01, 0x00, 0x07 ],
+  [ 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x03, 0x01, 0x01 ],
+  [ 0x05, 0x01, 0x01, 0x04, 0x19, 0x07, 0x18, 0x0D, 0x00 ],
+  [ 0x11, 0x09, 0x01, 0x21, 0x05, 0x20, 0x01, 0x00, 0x03 ],
+  [ 0x41, 0x01, 0x00, 0x05, 0x40, 0x03, 0x09, 0x21, 0x11 ],
+  [ 0x29, 0x01, 0x00, 0x28, 0x09, 0x15, 0x03, 0x08, 0x0B ],
+  [ 0x01, 0x00, 0x01, 0x11, 0x09, 0x10, 0x05, 0x01, 0x03 ],
+  [ 0x05, 0x01, 0x01, 0x04, 0x0D, 0x0C, 0x07, 0x00, 0x01 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x00, 0x03, 0x05, 0x11, 0x10, 0x25, 0x24, 0x13 ],
+  [ 0x21, 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x20, 0x09 ],
+  [ 0x01, 0x01, 0x01, 0x00, 0x09, 0x11, 0x10, 0x05, 0x03 ],
+  [ 0x21, 0x05, 0x01, 0x01, 0x09, 0x00, 0x11, 0x20, 0x03 ],
+  [ 0x05, 0x01, 0x00, 0x04, 0x01, 0x19, 0x07, 0x18, 0x0D ],
+  [ 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x03, 0x10, 0x05 ],
+  [ 0x1D, 0x01, 0x05, 0x0D, 0x0C, 0x04, 0x00, 0x1C, 0x0F ],
+  [ 0x05, 0x19, 0x01, 0x04, 0x00, 0x18, 0x1B, 0x1A, 0x07 ],
+  [ 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x11, 0x10, 0x01 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x00, 0x03, 0x41, 0x05, 0x40, 0x09, 0x11, 0x21 ],
+  [ 0x05, 0x01, 0x01, 0x19, 0x04, 0x07, 0x00, 0x18, 0x0D ],
+  [ 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x03 ],
+  [ 0x01, 0x05, 0x00, 0x0D, 0x01, 0x04, 0x07, 0x19, 0x18 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02 ],
+  [ 0x31, 0x01, 0x05, 0x19, 0x04, 0x07, 0x00, 0x30, 0x0D ],
+  [ 0x01, 0x00, 0x03, 0x11, 0x01, 0x05, 0x01, 0x09, 0x10 ],
+  [ 0x01, 0x05, 0x01, 0x11, 0x01, 0x10, 0x00, 0x03, 0x09 ],
+  [ 0x01, 0x09, 0x00, 0x29, 0x03, 0x08, 0x28, 0x15, 0x0B ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x01, 0x00, 0x09, 0x15, 0x03, 0x08, 0x14, 0x0B ],
+  [ 0x11, 0x01, 0x01, 0x00, 0x09, 0x01, 0x03, 0x10, 0x05 ],
+  [ 0x01, 0x00, 0x03, 0x25, 0x11, 0x05, 0x10, 0x24, 0x13 ],
+  [ 0x11, 0x01, 0x00, 0x01, 0x09, 0x01, 0x05, 0x10, 0x03 ],
+  [ 0x05, 0x01, 0x00, 0x0D, 0x0C, 0x04, 0x0F, 0x1D, 0x1C ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x03, 0x02 ],
+  [ 0x21, 0x01, 0x05, 0x09, 0x11, 0x00, 0x03, 0x41, 0x40 ],
+  [ 0x05, 0x01, 0x00, 0x1D, 0x1C, 0x0D, 0x0C, 0x0F, 0x04 ],
+  [ 0x05, 0x01, 0x00, 0x0D, 0x31, 0x04, 0x19, 0x30, 0x07 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x01, 0x00, 0x21, 0x05, 0x11, 0x03, 0x09, 0x20 ],
+  [ 0x01, 0x01, 0x00, 0x11, 0x03, 0x05, 0x01, 0x09, 0x10 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02 ],
+  [ 0x05, 0x01, 0x04, 0x19, 0x07, 0x0D, 0x00, 0x31, 0x30 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02 ],
+  [ 0x05, 0x01, 0x01, 0x11, 0x09, 0x00, 0x03, 0x21, 0x20 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02 ],
+  [ 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x01, 0x01, 0x02 ],
+  [ 0x09, 0x01, 0x00, 0x29, 0x08, 0x15, 0x03, 0x28, 0x0B ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03 ],
+  [ 0x09, 0x01, 0x00, 0x29, 0x28, 0x15, 0x08, 0x03, 0x0B ],
+  [ 0x01, 0x00, 0x01, 0x11, 0x05, 0x10, 0x09, 0x01, 0x03 ],
+  [ 0x05, 0x04, 0x01, 0x1D, 0x0D, 0x0C, 0x1C, 0x00, 0x0F ],
+  [ 0x09, 0x11, 0x01, 0x41, 0x00, 0x40, 0x05, 0x03, 0x21 ],
+  [ 0x0D, 0x05, 0x01, 0x1D, 0x1C, 0x0C, 0x04, 0x00, 0x0F ],
+  [ 0x41, 0x09, 0x01, 0x40, 0x00, 0x11, 0x05, 0x03, 0x21 ],
+  [ 0x01, 0x01, 0x01, 0x05, 0x01, 0x04, 0x00, 0x01, 0x03 ],
+  [ 0x05, 0x04, 0x01, 0x0D, 0x01, 0x0C, 0x07, 0x01, 0x00 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+
+  [ 0x05, 0x04, 0x01, 0x07, 0x19, 0x31, 0x30, 0x0D, 0x00 ],
+  [ 0x21, 0x01, 0x01, 0x00, 0x11, 0x09, 0x20, 0x05, 0x03 ],
+  [ 0x05, 0x01, 0x01, 0x04, 0x07, 0x0D, 0x0C, 0x00, 0x01 ],
+  [ 0x21, 0x09, 0x01, 0x00, 0x20, 0x05, 0x23, 0x22, 0x03 ],
+  [ 0x31, 0x0D, 0x01, 0x19, 0x05, 0x30, 0x04, 0x07, 0x00 ],
+  [ 0x31, 0x05, 0x01, 0x04, 0x19, 0x00, 0x0D, 0x30, 0x07 ],
+  [ 0x31, 0x01, 0x00, 0x0D, 0x05, 0x19, 0x04, 0x30, 0x07 ],
+  [ 0x01, 0x01, 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x01 ],
+  [ 0x01, 0x00, 0x01, 0x01, 0x05, 0x09, 0x08, 0x03, 0x01 ],
+  [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+];
+static RV40_AIC_MODE1_BITS: [[u8; 9]; 90] = [
+  [  1,  4,  2,  7,  4,  6,  4,  7,  5 ],
+  [  5,  1,  3,  4,  6,  3,  3,  7,  7 ],
+  [  1,  4,  2,  7,  6,  7,  5,  4,  4 ],
+  [  1,  3,  3,  3,  7,  4,  5,  7,  6 ],
+  [  2,  4,  2,  6,  4,  5,  2,  4,  6 ],
+  [  7,  2,  3,  4,  7,  1,  5,  7,  7 ],
+  [  5,  1,  3,  6,  5,  5,  2,  7,  7 ],
+  [  2,  5,  1,  7,  3,  7,  5,  5,  6 ],
+  [  2,  4,  1,  4,  5,  7,  6,  7,  4 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  2,  1,  3,  6,  5,  5,  5,  7,  7 ],
+  [  5,  1,  3,  4,  6,  3,  3,  7,  7 ],
+  [  4,  1,  2,  6,  5,  5,  4,  5,  6 ],
+  [  3,  1,  3,  4,  6,  3,  5,  7,  7 ],
+  [  4,  1,  3,  6,  3,  5,  3,  7,  7 ],
+  [  6,  1,  4,  4,  5,  2,  4,  7,  7 ],
+  [  7,  1,  5,  7,  4,  3,  2,  7,  7 ],
+  [  5,  3,  2,  7,  5,  6,  1,  5,  7 ],
+  [  4,  1,  2,  6,  7,  5,  4,  7,  4 ],
+  [  1,  0,  1,  0,  0,  0,  0,  0,  0 ],
+
+  [  3,  3,  1,  5,  5,  6,  6,  5,  3 ],
+  [  6,  2,  1,  5,  6,  5,  4,  4,  5 ],
+  [  6,  4,  1,  7,  6,  7,  6,  3,  2 ],
+  [  4,  3,  1,  4,  6,  4,  6,  5,  3 ],
+  [  6,  5,  1,  7,  4,  7,  3,  3,  3 ],
+  [  7,  2,  2,  3,  7,  2,  4,  6,  5 ],
+  [  6,  2,  2,  6,  4,  5,  2,  4,  4 ],
+  [  4,  4,  1,  7,  6,  7,  5,  2,  4 ],
+  [  5,  4,  1,  5,  6,  6,  5,  4,  2 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  2,  2,  2,  3,  5,  5,  6,  6,  5 ],
+  [  7,  1,  3,  3,  6,  3,  4,  7,  5 ],
+  [  2,  4,  1,  4,  6,  7,  7,  5,  4 ],
+  [  7,  4,  3,  1,  5,  3,  6,  7,  3 ],
+  [  4,  3,  3,  4,  1,  6,  4,  6,  5 ],
+  [  7,  4,  4,  2,  6,  1,  4,  7,  5 ],
+  [  5,  2,  3,  4,  4,  3,  2,  5,  4 ],
+  [  3,  5,  2,  3,  2,  5,  5,  5,  3 ],
+  [  6,  4,  4,  2,  5,  4,  7,  7,  1 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  2,  2,  2,  7,  3,  7,  4,  5,  6 ],
+  [  4,  1,  3,  6,  4,  4,  3,  6,  5 ],
+  [  2,  4,  1,  7,  3,  7,  6,  6,  6 ],
+  [  3,  4,  3,  5,  1,  4,  4,  6,  6 ],
+  [  4,  5,  2,  7,  1,  7,  3,  7,  7 ],
+  [  6,  2,  3,  5,  3,  3,  2,  6,  4 ],
+  [  4,  4,  4,  7,  2,  5,  1,  6,  7 ],
+  [  4,  5,  2,  7,  1,  7,  4,  4,  6 ],
+  [  2,  4,  2,  6,  2,  4,  6,  5,  4 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  1,  3,  3,  5,  6,  3,  5,  6,  5 ],
+  [  7,  1,  4,  4,  6,  2,  4,  7,  5 ],
+  [  2,  2,  2,  6,  5,  3,  5,  6,  5 ],
+  [  7,  4,  4,  2,  6,  1,  5,  7,  4 ],
+  [  3,  2,  2,  4,  4,  3,  4,  5,  5 ],
+  [  7,  2,  5,  3,  7,  1,  4,  7,  7 ],
+  [  6,  2,  3,  4,  5,  2,  2,  7,  7 ],
+  [  3,  2,  2,  5,  5,  4,  4,  4,  3 ],
+  [  3,  2,  2,  4,  6,  3,  5,  6,  3 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  1,  3,  3,  7,  4,  6,  3,  5,  7 ],
+  [  4,  1,  4,  7,  4,  5,  2,  6,  7 ],
+  [  2,  4,  1,  7,  5,  7,  3,  7,  7 ],
+  [  3,  2,  3,  5,  3,  4,  2,  6,  6 ],
+  [  3,  5,  4,  7,  2,  7,  1,  7,  7 ],
+  [  4,  1,  3,  6,  5,  3,  3,  7,  7 ],
+  [  4,  2,  5,  7,  3,  7,  1,  7,  7 ],
+  [  7,  4,  1,  7,  3,  7,  2,  5,  7 ],
+  [  4,  2,  2,  6,  4,  5,  2,  6,  4 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  3,  4,  1,  7,  6,  7,  6,  2,  6 ],
+  [  4,  2,  2,  6,  6,  5,  4,  2,  4 ],
+  [  4,  4,  1,  7,  5,  7,  6,  2,  4 ],
+  [  3,  3,  2,  5,  4,  4,  5,  2,  4 ],
+  [  4,  5,  2,  7,  2,  7,  3,  2,  6 ],
+  [  4,  3,  2,  5,  5,  4,  3,  2,  4 ],
+  [  7,  4,  2,  7,  2,  5,  3,  2,  6 ],
+  [  4,  6,  2,  7,  3,  7,  6,  1,  6 ],
+  [  5,  5,  1,  6,  4,  6,  5,  2,  4 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+
+  [  3,  3,  2,  3,  5,  6,  6,  4,  2 ],
+  [  7,  1,  3,  3,  6,  5,  7,  4,  3 ],
+  [  5,  4,  1,  5,  5,  6,  6,  4,  2 ],
+  [  6,  4,  2,  2,  6,  3,  6,  6,  2 ],
+  [  6,  4,  2,  5,  3,  6,  3,  3,  2 ],
+  [  6,  3,  2,  3,  5,  2,  4,  6,  3 ],
+  [  6,  2,  2,  4,  3,  5,  3,  6,  3 ],
+  [  7,  5,  1,  7,  4,  7,  7,  3,  2 ],
+  [  5,  5,  2,  3,  6,  7,  7,  5,  1 ],
+  [  0,  0,  0,  0,  0,  0,  0,  0,  0 ],
+];
+
+const RV40_AIC_MODE2_CODES: [[u16; 81]; 20] = [
+  [
+    0x0001, 0x0001, 0x0005, 0x01F5, 0x0011, 0x0049, 0x0000, 0x0048, 0x004B,
+    0x0035, 0x0003, 0x0034, 0x03C9, 0x01F4, 0x00C9, 0x004A, 0x0FD9, 0x03C8,
+    0x0010, 0x0037, 0x0001, 0x00C8, 0x0075, 0x01F7, 0x00CB, 0x0074, 0x0002,
+    0x01F6, 0x00CA, 0x01F1, 0x01F0, 0x1F81, 0x07F9, 0x1F80, 0x1F83, 0x07F8,
+    0x0077, 0x00F5, 0x0036, 0x07FB, 0x0076, 0x1F82, 0x00F4, 0x00F7, 0x07FA,
+    0x0071, 0x00F6, 0x03CB, 0x03CA, 0x0FD8, 0x00F1, 0x03F5, 0x1F8D, 0x07E5,
+    0x0013, 0x0031, 0x00F0, 0x0FDB, 0x00F3, 0x07E4, 0x0030, 0x01F3, 0x07E7,
+    0x03F4, 0x07E6, 0x0070, 0x3F19, 0x01F2, 0x3F18, 0x0FDA, 0x0033, 0x07E1,
+    0x01FD, 0x01FC, 0x0073, 0x01FF, 0x0FC5, 0x0FC4, 0x0FC7, 0x03F7, 0x0072,
+  ], [
+    0x0005, 0x0005, 0x0005, 0x0079, 0x0005, 0x000D, 0x001D, 0x0078, 0x0069,
+    0x0004, 0x0001, 0x0007, 0x0068, 0x001C, 0x001F, 0x0004, 0x006B, 0x000C,
+    0x0004, 0x001E, 0x0006, 0x006A, 0x0015, 0x000F, 0x0014, 0x0017, 0x0007,
+    0x0016, 0x000E, 0x0011, 0x0009, 0x00D1, 0x00D0, 0x0181, 0x00D3, 0x007B,
+    0x0010, 0x0013, 0x0004, 0x00D2, 0x0007, 0x0319, 0x0008, 0x007A, 0x00DD,
+    0x0019, 0x0006, 0x000B, 0x0065, 0x00DC, 0x0012, 0x0064, 0x0180, 0x00DF,
+    0x0006, 0x0018, 0x0001, 0x00DE, 0x001D, 0x00D9, 0x001B, 0x0067, 0x000A,
+    0x00D8, 0x00DB, 0x001C, 0x0318, 0x00DA, 0x0635, 0x0183, 0x0000, 0x00C5,
+    0x0066, 0x0061, 0x0035, 0x00C4, 0x0182, 0x0634, 0x031B, 0x00C7, 0x001F,
+  ], [
+    0x0005, 0x0001, 0x001D, 0x01C1, 0x0035, 0x00F1, 0x006D, 0x00F0, 0x0049,
+    0x0000, 0x0004, 0x0003, 0x00F3, 0x0048, 0x0034, 0x006C, 0x01C0, 0x01C3,
+    0x0007, 0x0006, 0x0001, 0x006F, 0x0002, 0x004B, 0x006E, 0x001C, 0x0005,
+    0x0069, 0x0068, 0x006B, 0x0037, 0x01C2, 0x00F2, 0x0395, 0x01CD, 0x00FD,
+    0x006A, 0x0036, 0x0015, 0x01CC, 0x0014, 0x0394, 0x004A, 0x00FC, 0x00FF,
+    0x0017, 0x0031, 0x00FE, 0x01CF, 0x0397, 0x00F9, 0x01CE, 0x0725, 0x0396,
+    0x0016, 0x0030, 0x0075, 0x0724, 0x00F8, 0x0727, 0x0033, 0x0391, 0x0390,
+    0x0011, 0x0032, 0x001F, 0x00FB, 0x0074, 0x0726, 0x00FA, 0x001E, 0x0077,
+    0x0019, 0x0018, 0x0004, 0x0010, 0x003D, 0x0076, 0x0071, 0x0013, 0x0001,
+  ], [
+    0x000D, 0x0019, 0x0011, 0x0015, 0x0061, 0x0019, 0x0014, 0x01AD, 0x0060,
+    0x0018, 0x0001, 0x0005, 0x001B, 0x0010, 0x0019, 0x0005, 0x0017, 0x0018,
+    0x0016, 0x0004, 0x0004, 0x0013, 0x000C, 0x0012, 0x001A, 0x0018, 0x0005,
+    0x000F, 0x001B, 0x0004, 0x001D, 0x0011, 0x001C, 0x0010, 0x000E, 0x001B,
+    0x0013, 0x001F, 0x001A, 0x0029, 0x0005, 0x0063, 0x001E, 0x0009, 0x0062,
+    0x0008, 0x0007, 0x0007, 0x0019, 0x0004, 0x001A, 0x0018, 0x006D, 0x0007,
+    0x001B, 0x0007, 0x001A, 0x006C, 0x0006, 0x0012, 0x0005, 0x006F, 0x000B,
+    0x006E, 0x0069, 0x001D, 0x0359, 0x0028, 0x002B, 0x002A, 0x001C, 0x00D5,
+    0x0358, 0x001F, 0x0001, 0x001E, 0x0068, 0x00D4, 0x00D7, 0x0019, 0x0000,
+  ], [
+    0x00B9, 0x0061, 0x0060, 0x00B8, 0x02B5, 0x01AD, 0x00BB, 0x0AF5, 0x0151,
+    0x0001, 0x0001, 0x0005, 0x0000, 0x0003, 0x0005, 0x0004, 0x0063, 0x0025,
+    0x00BA, 0x0004, 0x0007, 0x0062, 0x00A5, 0x0024, 0x006D, 0x0002, 0x006C,
+    0x02B4, 0x000D, 0x006F, 0x0027, 0x00A4, 0x0026, 0x01AC, 0x0150, 0x01AF,
+    0x01AE, 0x0021, 0x006E, 0x02B7, 0x0020, 0x0153, 0x0023, 0x00A7, 0x0152,
+    0x00A6, 0x0006, 0x000C, 0x0022, 0x01A9, 0x0019, 0x002D, 0x02B6, 0x01A8,
+    0x000F, 0x0007, 0x000E, 0x00A1, 0x0069, 0x002C, 0x0001, 0x01AB, 0x00A0,
+    0x02B1, 0x00A3, 0x002F, 0x0AF4, 0x02B0, 0x0AF7, 0x02B3, 0x0068, 0x015D,
+    0x0AF6, 0x01AA, 0x0055, 0x015C, 0x02B2, 0x0579, 0x0578, 0x015F, 0x00A2,
+  ], [
+    0x0905, 0x013D, 0x013C, 0x0904, 0x121D, 0x049D, 0x049C, 0x243D, 0x0907,
+    0x00ED, 0x0001, 0x0015, 0x0041, 0x013F, 0x0031, 0x0014, 0x025D, 0x025C,
+    0x013E, 0x000D, 0x0000, 0x0040, 0x0139, 0x0043, 0x0030, 0x0017, 0x0033,
+    0x0906, 0x0032, 0x0042, 0x00EC, 0x025F, 0x00EF, 0x025E, 0x049F, 0x0138,
+    0x0901, 0x013B, 0x0259, 0x121C, 0x049E, 0x0900, 0x0258, 0x243C, 0x121F,
+    0x0903, 0x003D, 0x00EE, 0x025B, 0x025A, 0x004D, 0x013A, 0x0902, 0x0245,
+    0x00E9, 0x0016, 0x00E8, 0x0499, 0x0125, 0x0244, 0x004C, 0x0498, 0x090D,
+    0x00EB, 0x003C, 0x0011, 0x049B, 0x049A, 0x0485, 0x00EA, 0x003F, 0x0124,
+    0x090C, 0x003E, 0x0039, 0x0095, 0x0247, 0x0246, 0x0484, 0x0094, 0x0038,
+  ], [
+    0x0F09, 0x00CD, 0x01FD, 0x0791, 0x1E6D, 0x0790, 0x03D9, 0x3CD1, 0x3CD0,
+    0x0075, 0x0001, 0x0001, 0x0035, 0x00CC, 0x0011, 0x0000, 0x03D8, 0x01FC,
+    0x03DB, 0x0010, 0x0003, 0x00CF, 0x03DA, 0x00CE, 0x0074, 0x0034, 0x0077,
+    0x0793, 0x0013, 0x0076, 0x0071, 0x03C5, 0x0070, 0x01FF, 0x0792, 0x01FE,
+    0x01F9, 0x0037, 0x00C9, 0x0F08, 0x01F8, 0x03C4, 0x00C8, 0x0F0B, 0x079D,
+    0x03C7, 0x0001, 0x0012, 0x0073, 0x00CB, 0x0005, 0x0036, 0x03C6, 0x0072,
+    0x007D, 0x0002, 0x00CA, 0x079C, 0x01FB, 0x00F5, 0x0031, 0x079F, 0x0F0A,
+    0x0F35, 0x079E, 0x01FA, 0x1E6C, 0x1E6F, 0x3CD3, 0x0799, 0x03C1, 0x1E6E,
+    0x3CD2, 0x0030, 0x00F4, 0x007C, 0x03C0, 0x03C3, 0x0798, 0x01E5, 0x00F7,
+  ], [
+    0x01A5, 0x0001, 0x001D, 0x0021, 0x00A1, 0x000D, 0x0061, 0x06B9, 0x00A0,
+    0x0060, 0x0001, 0x0005, 0x000C, 0x0020, 0x001C, 0x0004, 0x01A4, 0x01A7,
+    0x00A3, 0x001F, 0x001E, 0x0023, 0x0022, 0x002D, 0x002C, 0x0063, 0x0062,
+    0x1A81, 0x01A6, 0x01A1, 0x06B8, 0x06BB, 0x00A2, 0x06BA, 0x0D59, 0x06A5,
+    0x01A0, 0x000F, 0x006D, 0x06A4, 0x002F, 0x00AD, 0x006C, 0x06A7, 0x00AC,
+    0x0D58, 0x000E, 0x01A3, 0x00AF, 0x00AE, 0x006F, 0x01A2, 0x0D5B, 0x00A9,
+    0x0019, 0x0001, 0x0009, 0x00A8, 0x006E, 0x002E, 0x0000, 0x01AD, 0x00AB,
+    0x00AA, 0x0355, 0x0029, 0x1A80, 0x1A83, 0x1A82, 0x0354, 0x01AC, 0x0D5A,
+    0x1A8D, 0x01AF, 0x0357, 0x0D45, 0x0D44, 0x0D47, 0x1A8C, 0x06A6, 0x06A1,
+  ], [
+    0x0001, 0x0011, 0x0005, 0x0775, 0x00F9, 0x00F8, 0x0031, 0x0030, 0x0049,
+    0x00FB, 0x0010, 0x0033, 0x0EC9, 0x038D, 0x038C, 0x00FA, 0x038F, 0x0774,
+    0x0048, 0x0032, 0x0000, 0x01D5, 0x00E5, 0x038E, 0x00E4, 0x0013, 0x000D,
+    0x0389, 0x0777, 0x0388, 0x038B, 0x1DF9, 0x0EC8, 0x3BC9, 0x1DF8, 0x038A,
+    0x03B5, 0x0776, 0x00E7, 0x3BC8, 0x01D4, 0x3BCB, 0x0ECB, 0x0771, 0x0ECA,
+    0x01D7, 0x03B4, 0x01D6, 0x1DFB, 0x0EF5, 0x0770, 0x0EF4, 0x3BCA, 0x0773,
+    0x00E6, 0x03B7, 0x004B, 0x1DFA, 0x03B6, 0x0EF7, 0x00E1, 0x0EF6, 0x0EF1,
+    0x03B1, 0x01D1, 0x003D, 0x0EF0, 0x0772, 0x077D, 0x077C, 0x003C, 0x01D0,
+    0x03B0, 0x01D3, 0x003F, 0x03B3, 0x01D2, 0x0EF3, 0x077F, 0x00E0, 0x004A,
+  ], [
+    0x0015, 0x0049, 0x0014, 0x07D1, 0x03FD, 0x03FC, 0x01C1, 0x01C0, 0x00F1,
+    0x0017, 0x0001, 0x0001, 0x01C3, 0x0048, 0x004B, 0x0016, 0x0031, 0x01C2,
+    0x004A, 0x0011, 0x0000, 0x01CD, 0x00F0, 0x01CC, 0x0075, 0x0010, 0x000D,
+    0x03FF, 0x01CF, 0x01CE, 0x07D0, 0x0F81, 0x07D3, 0x1F1D, 0x0F80, 0x07D2,
+    0x01C9, 0x03FE, 0x0074, 0x07DD, 0x00F3, 0x1F1C, 0x07DC, 0x03F9, 0x07DF,
+    0x00F2, 0x00FD, 0x0077, 0x07DE, 0x07D9, 0x01C8, 0x07D8, 0x0F83, 0x03F8,
+    0x0030, 0x0076, 0x0013, 0x0F82, 0x00FC, 0x03FB, 0x0033, 0x03FA, 0x03E5,
+    0x03E4, 0x01CB, 0x0032, 0x1F1F, 0x03E7, 0x07DB, 0x07DA, 0x003D, 0x01CA,
+    0x07C5, 0x03E6, 0x0071, 0x0F8D, 0x07C4, 0x1F1E, 0x0F8C, 0x03E1, 0x01F5,
+  ], [
+    0x0019, 0x0065, 0x0018, 0x0351, 0x0350, 0x0353, 0x0021, 0x0020, 0x0064,
+    0x001D, 0x0005, 0x0005, 0x01A5, 0x0023, 0x0067, 0x0005, 0x0066, 0x0022,
+    0x001B, 0x0004, 0x0001, 0x0004, 0x001C, 0x0061, 0x001A, 0x0005, 0x0004,
+    0x0007, 0x002D, 0x0006, 0x002C, 0x01A4, 0x002F, 0x0352, 0x035D, 0x0060,
+    0x0001, 0x002E, 0x001F, 0x035C, 0x0000, 0x06B1, 0x01A7, 0x0029, 0x01A6,
+    0x0028, 0x0063, 0x0062, 0x035F, 0x01A1, 0x002B, 0x06B0, 0x06B3, 0x01A0,
+    0x0003, 0x006D, 0x001E, 0x035E, 0x006C, 0x06B2, 0x0002, 0x01A3, 0x01A2,
+    0x000D, 0x0005, 0x0007, 0x01AD, 0x006F, 0x002A, 0x006E, 0x0004, 0x0004,
+    0x000C, 0x0007, 0x0006, 0x000F, 0x000E, 0x00D5, 0x0009, 0x0006, 0x0007,
+  ], [
+    0x0065, 0x0181, 0x0064, 0x36C9, 0x06D5, 0x0DB5, 0x0379, 0x0180, 0x0183,
+    0x00D5, 0x001D, 0x001C, 0x0DB4, 0x0182, 0x0378, 0x00D4, 0x00D7, 0x06D4,
+    0x0067, 0x001F, 0x0001, 0x00D6, 0x00D1, 0x018D, 0x0066, 0x0001, 0x0000,
+    0x037B, 0x06D7, 0x037A, 0x0DB7, 0x36C8, 0x06D6, 0x0DB6, 0x1B79, 0x0DB1,
+    0x018C, 0x0365, 0x00D0, 0x1B78, 0x00D3, 0x1B7B, 0x0364, 0x06D1, 0x06D0,
+    0x018F, 0x018E, 0x00D2, 0x36CB, 0x0367, 0x0366, 0x06D3, 0x0DB0, 0x06D2,
+    0x0361, 0x06DD, 0x0189, 0x36CA, 0x0360, 0x36F5, 0x0188, 0x0DB3, 0x36F4,
+    0x0009, 0x0008, 0x0005, 0x06DC, 0x00DD, 0x018B, 0x00DC, 0x0004, 0x000B,
+    0x018A, 0x0061, 0x0003, 0x0363, 0x00DF, 0x06DF, 0x0362, 0x000A, 0x001E,
+  ], [
+    0x001D, 0x0061, 0x000D, 0x0D55, 0x06B9, 0x06B8, 0x01A5, 0x0021, 0x0020,
+    0x0023, 0x000C, 0x0060, 0x0D54, 0x00AD, 0x00AC, 0x0022, 0x00AF, 0x06BB,
+    0x000F, 0x001C, 0x0001, 0x002D, 0x0063, 0x01A4, 0x000E, 0x0001, 0x0005,
+    0x01A7, 0x06BA, 0x01A6, 0x06A5, 0x0D57, 0x0D56, 0x1ABD, 0x0D51, 0x00AE,
+    0x002C, 0x00A9, 0x002F, 0x0D50, 0x01A1, 0x1ABC, 0x06A4, 0x06A7, 0x06A6,
+    0x00A8, 0x06A1, 0x01A0, 0x1ABF, 0x0D53, 0x06A0, 0x0D52, 0x1ABE, 0x06A3,
+    0x0062, 0x002E, 0x0009, 0x0D5D, 0x01A3, 0x0D5C, 0x006D, 0x00AB, 0x06A2,
+    0x006C, 0x001F, 0x0001, 0x06AD, 0x0029, 0x01A2, 0x0028, 0x0004, 0x001E,
+    0x01AD, 0x006F, 0x0000, 0x01AC, 0x01AF, 0x06AC, 0x00AA, 0x006E, 0x0019,
+  ], [
+    0x0019, 0x007D, 0x0018, 0x01B5, 0x000D, 0x01B4, 0x007C, 0x007F, 0x01B7,
+    0x000C, 0x001B, 0x001A, 0x01B6, 0x000F, 0x00D5, 0x0019, 0x007E, 0x00D4,
+    0x0018, 0x001B, 0x0001, 0x000E, 0x0011, 0x0009, 0x0005, 0x0005, 0x0005,
+    0x00D7, 0x01B1, 0x0008, 0x01B0, 0x0079, 0x06FD, 0x0371, 0x0370, 0x00D6,
+    0x0078, 0x01B3, 0x0010, 0x0373, 0x0013, 0x06FC, 0x007B, 0x007A, 0x00D1,
+    0x00D0, 0x00D3, 0x0065, 0x0372, 0x06FF, 0x0064, 0x06FE, 0x037D, 0x00D2,
+    0x00DD, 0x0067, 0x0004, 0x037C, 0x0012, 0x01B2, 0x0007, 0x0066, 0x01BD,
+    0x0006, 0x0061, 0x0004, 0x01BC, 0x001A, 0x0060, 0x001D, 0x0004, 0x001C,
+    0x0063, 0x0001, 0x0007, 0x000B, 0x0000, 0x0062, 0x000A, 0x0005, 0x0007,
+  ], [
+    0x0069, 0x0045, 0x0068, 0x04BD, 0x0255, 0x04BC, 0x00E5, 0x00E4, 0x0031,
+    0x0030, 0x0019, 0x0001, 0x0121, 0x00E7, 0x00E6, 0x0033, 0x00E1, 0x00E0,
+    0x006B, 0x0018, 0x0001, 0x0044, 0x0032, 0x0047, 0x006A, 0x001B, 0x0005,
+    0x003D, 0x0046, 0x0015, 0x0041, 0x0120, 0x0123, 0x04BF, 0x0122, 0x0040,
+    0x003C, 0x00E3, 0x0014, 0x0254, 0x0043, 0x0975, 0x012D, 0x00E2, 0x00ED,
+    0x0042, 0x00EC, 0x004D, 0x0257, 0x0256, 0x0251, 0x04BE, 0x0974, 0x0250,
+    0x00EF, 0x00EE, 0x004C, 0x04B9, 0x012C, 0x04B8, 0x004F, 0x04BB, 0x0253,
+    0x003F, 0x0017, 0x0001, 0x0252, 0x00E9, 0x00E8, 0x00EB, 0x0000, 0x0003,
+    0x0016, 0x0002, 0x0004, 0x004E, 0x003E, 0x00EA, 0x0049, 0x000D, 0x0007,
+  ], [
+    0x000D, 0x01BD, 0x000C, 0x0D31, 0x0D30, 0x0D33, 0x0359, 0x0358, 0x002D,
+    0x0065, 0x001D, 0x001C, 0x0D32, 0x035B, 0x035A, 0x002C, 0x01BC, 0x0345,
+    0x000F, 0x001F, 0x0001, 0x002F, 0x0064, 0x01BF, 0x0067, 0x0001, 0x0005,
+    0x0066, 0x002E, 0x0061, 0x0029, 0x0695, 0x0694, 0x0697, 0x0696, 0x0060,
+    0x01BE, 0x0D3D, 0x0028, 0x1A49, 0x0344, 0x1A48, 0x1A4B, 0x0D3C, 0x0691,
+    0x002B, 0x01B9, 0x002A, 0x0D3F, 0x0690, 0x0347, 0x0D3E, 0x1A4A, 0x0346,
+    0x00D5, 0x0341, 0x0063, 0x0D39, 0x0340, 0x0D38, 0x01B8, 0x0D3B, 0x0D3A,
+    0x00D4, 0x0062, 0x0000, 0x0693, 0x01BB, 0x0343, 0x0342, 0x001E, 0x000E,
+    0x006D, 0x0009, 0x0001, 0x006C, 0x00D7, 0x034D, 0x01BA, 0x0008, 0x0004,
+  ], [
+    0x0075, 0x00CD, 0x0035, 0x03C1, 0x03C0, 0x07F9, 0x03C3, 0x1F8D, 0x00CC,
+    0x0074, 0x0011, 0x0010, 0x03C2, 0x0FD9, 0x01F1, 0x00CF, 0x03CD, 0x00CE,
+    0x0034, 0x0001, 0x0001, 0x0037, 0x00C9, 0x00C8, 0x0036, 0x0000, 0x0001,
+    0x0FD8, 0x03CC, 0x00CB, 0x01F0, 0x07F8, 0x03CF, 0x07FB, 0x07FA, 0x00CA,
+    0x01F3, 0x03CE, 0x00F5, 0x0FDB, 0x00F4, 0x07E5, 0x07E4, 0x07E7, 0x01F2,
+    0x07E6, 0x03C9, 0x01FD, 0x0FDA, 0x1F8C, 0x07E1, 0x1F8F, 0x1F8E, 0x03C8,
+    0x03CB, 0x0077, 0x0076, 0x0FC5, 0x03CA, 0x07E0, 0x00F7, 0x0FC4, 0x03F5,
+    0x00F6, 0x01FC, 0x0003, 0x03F4, 0x0071, 0x03F7, 0x00F1, 0x0013, 0x0031,
+    0x0030, 0x0070, 0x0005, 0x0012, 0x0073, 0x01FF, 0x0072, 0x007D, 0x0002,
+  ], [
+    0x0061, 0x0055, 0x0060, 0x02C9, 0x02C8, 0x02CB, 0x0171, 0x00B5, 0x0054,
+    0x0001, 0x0001, 0x0001, 0x0057, 0x0001, 0x0063, 0x001D, 0x0062, 0x0039,
+    0x006D, 0x0000, 0x0005, 0x0038, 0x0056, 0x00B4, 0x006C, 0x0003, 0x001C,
+    0x006F, 0x003B, 0x0002, 0x003A, 0x0170, 0x00B7, 0x0173, 0x0051, 0x006E,
+    0x0025, 0x0050, 0x0069, 0x02CA, 0x0024, 0x0027, 0x0172, 0x00B6, 0x00B1,
+    0x000D, 0x000C, 0x001F, 0x017D, 0x0026, 0x0068, 0x0053, 0x017C, 0x006B,
+    0x001E, 0x000F, 0x0004, 0x017F, 0x006A, 0x02F5, 0x0019, 0x0021, 0x0052,
+    0x02F4, 0x02F7, 0x0020, 0x0BCD, 0x05E5, 0x05E4, 0x0BCC, 0x0023, 0x00B0,
+    0x02F6, 0x00B3, 0x0022, 0x02F1, 0x02F0, 0x0BCF, 0x0BCE, 0x017E, 0x005D,
+  ], [
+    0x00BD, 0x0025, 0x01A1, 0x0159, 0x0299, 0x00BC, 0x0024, 0x0505, 0x0504,
+    0x01A0, 0x0001, 0x001D, 0x006D, 0x001C, 0x0001, 0x0005, 0x0027, 0x01A3,
+    0x0158, 0x001F, 0x001E, 0x01A2, 0x0026, 0x0021, 0x000D, 0x0020, 0x0023,
+    0x0298, 0x006C, 0x0022, 0x00BF, 0x00BE, 0x01AD, 0x002D, 0x029B, 0x00B9,
+    0x01AC, 0x00B8, 0x01AF, 0x029A, 0x006F, 0x015B, 0x006E, 0x0285, 0x0284,
+    0x01AE, 0x0019, 0x002C, 0x01A9, 0x01A8, 0x000C, 0x000F, 0x015A, 0x00BB,
+    0x000E, 0x0000, 0x0069, 0x01AB, 0x0018, 0x01AA, 0x0004, 0x0055, 0x00BA,
+    0x0507, 0x0145, 0x0054, 0x0506, 0x00A5, 0x0501, 0x00A4, 0x0057, 0x0500,
+    0x0A05, 0x0144, 0x00A7, 0x0287, 0x0286, 0x0503, 0x0147, 0x0A04, 0x0146,
+  ], [
+    0x0759, 0x0041, 0x00E5, 0x03BD, 0x0E9D, 0x012D, 0x012C, 0x3A1D, 0x03BC,
+    0x012F, 0x000D, 0x0040, 0x00E4, 0x03BF, 0x0043, 0x0042, 0x0758, 0x03BE,
+    0x00E7, 0x0001, 0x0000, 0x003D, 0x00E6, 0x0015, 0x0014, 0x0017, 0x003C,
+    0x743D, 0x012E, 0x03B9, 0x03B8, 0x0E9C, 0x03BB, 0x075B, 0x3A1C, 0x0E9F,
+    0x0129, 0x00E1, 0x0128, 0x0E9E, 0x012B, 0x075A, 0x00E0, 0x0E99, 0x0745,
+    0x3A1F, 0x03BA, 0x0744, 0x0E98, 0x1D0D, 0x03A5, 0x0E9B, 0x743C, 0x0E9A,
+    0x012A, 0x004D, 0x00E3, 0x0E85, 0x01D5, 0x0E84, 0x004C, 0x0747, 0x1D0C,
+    0x01D4, 0x003F, 0x0016, 0x0746, 0x03A4, 0x0741, 0x004F, 0x003E, 0x01D7,
+    0x0740, 0x000C, 0x0011, 0x004E, 0x00E2, 0x00ED, 0x00EC, 0x0049, 0x0048,
+  ]
+];
+const RV40_AIC_MODE2_BITS: [[u8; 81]; 20] = [
+  [
+1,  5,  4, 10,  6,  8,  5,  8,  8,
+     7,  5,  7, 11, 10,  9,  8, 13, 11,
+     6,  7,  3,  9,  8, 10,  9,  8,  5,
+    10,  9, 10, 10, 14, 12, 14, 14, 12,
+     8,  9,  7, 12,  8, 14,  9,  9, 12,
+     8,  9, 11, 11, 13,  9, 11, 14, 12,
+     6,  7,  9, 13,  9, 12,  7, 10, 12,
+    11, 12,  8, 15, 10, 15, 13,  7, 12,
+    10, 10,  8, 10, 13, 13, 13, 11,  8,
+  ], [
+     4,  6,  5, 11,  8, 10,  7, 11,  9,
+     4,  1,  4,  9,  7,  7,  5,  9, 10,
+     6,  7,  4,  9,  9, 10,  9,  9,  6,
+     9, 10,  9, 10, 12, 12, 13, 12, 11,
+     9,  9,  8, 12,  8, 14, 10, 11, 12,
+     7,  8, 10, 11, 12,  9, 11, 13, 12,
+     6,  7,  8, 12,  9, 12,  7, 11, 10,
+    12, 12,  9, 14, 12, 15, 13,  8, 12,
+    11, 11, 10, 12, 13, 15, 14, 12,  9,
+  ], [
+     5,  7,  6, 12,  9, 11,  8, 11, 10,
+     7,  5,  7, 11, 10,  9,  8, 12, 12,
+     5,  5,  1,  8,  7, 10,  8,  6,  4,
+     8,  8,  8,  9, 12, 11, 13, 12, 11,
+     8,  9,  8, 12,  8, 13, 10, 11, 11,
+     8,  9, 11, 12, 13, 11, 12, 14, 13,
+     8,  9, 10, 14, 11, 14,  9, 13, 13,
+     8,  9,  6, 11, 10, 14, 11,  6, 10,
+     6,  6,  4,  8,  9, 10, 10,  8,  5,
+  ], [
+    11,  7,  8, 10, 12,  9, 10, 14, 12,
+     7,  1,  5,  7,  8,  6,  4, 10,  9,
+    10,  5,  4,  8, 11,  8,  7,  6,  7,
+    11,  6,  7,  8, 10,  8, 10, 11,  9,
+    10,  8,  9, 13,  9, 12,  8, 11, 12,
+    11,  4,  7,  8,  9,  6,  8, 12,  9,
+     8,  5,  8, 12,  9, 10,  6, 12, 11,
+    12, 12, 10, 15, 13, 13, 13, 10, 13,
+    15, 10,  9, 10, 12, 13, 13, 10,  9,
+  ], [
+    11,  8,  8, 11, 13, 10, 11, 15, 12,
+     7,  1,  4,  7,  7,  5,  4,  8,  9,
+    11,  5,  5,  8, 11,  9,  8,  7,  8,
+    13,  7,  8,  9, 11,  9, 10, 12, 10,
+    10,  9,  8, 13,  9, 12,  9, 11, 12,
+    11,  5,  7,  9, 10,  6,  9, 13, 10,
+     7,  4,  7, 11,  8,  9,  5, 10, 11,
+    13, 11,  9, 15, 13, 15, 13,  8, 12,
+    15, 10, 10, 12, 13, 14, 14, 12, 11,
+  ], [
+    12,  9,  9, 12, 13, 11, 11, 14, 12,
+     8,  2,  5,  7,  9,  6,  5, 10, 10,
+     9,  4,  2,  7,  9,  7,  6,  5,  6,
+    12,  6,  7,  8, 10,  8, 10, 11,  9,
+    12,  9, 10, 13, 11, 12, 10, 14, 13,
+    12,  6,  8, 10, 10,  7,  9, 12, 10,
+     8,  5,  8, 11,  9, 10,  7, 11, 12,
+     8,  6,  5, 11, 11, 11,  8,  6,  9,
+    12,  6,  6,  8, 10, 10, 11,  8,  6,
+  ], [
+    13,  9, 10, 12, 14, 12, 11, 15, 15,
+     8,  1,  5,  7,  9,  6,  5, 11, 10,
+    11,  6,  5,  9, 11,  9,  8,  7,  8,
+    12,  6,  8,  8, 11,  8, 10, 12, 10,
+    10,  7,  9, 13, 10, 11,  9, 13, 12,
+    11,  3,  6,  8,  9,  4,  7, 11,  8,
+     8,  5,  9, 12, 10,  9,  7, 12, 13,
+    13, 12, 10, 14, 14, 15, 12, 11, 14,
+    15,  7,  9,  8, 11, 11, 12, 10,  9,
+  ], [
+    10,  5,  6,  9, 11,  7,  8, 12, 11,
+     8,  1,  4,  7,  9,  6,  4, 10, 10,
+    11,  6,  6,  9,  9,  9,  9,  8,  8,
+    14, 10, 10, 12, 12, 11, 12, 13, 12,
+    10,  7,  8, 12,  9, 11,  8, 12, 11,
+    13,  7, 10, 11, 11,  8, 10, 13, 11,
+     6,  3,  7, 11,  8,  9,  5, 10, 11,
+    11, 11,  9, 14, 14, 14, 11, 10, 13,
+    14, 10, 11, 13, 13, 13, 14, 12, 12,
+  ], [
+     2,  5,  3, 11,  8,  8,  6,  6,  7,
+     8,  5,  6, 12, 10, 10,  8, 10, 11,
+     7,  6,  2,  9,  8, 10,  8,  5,  4,
+    10, 11, 10, 10, 13, 12, 14, 13, 10,
+    10, 11,  8, 14,  9, 14, 12, 11, 12,
+     9, 10,  9, 13, 12, 11, 12, 14, 11,
+     8, 10,  7, 13, 10, 12,  8, 12, 12,
+    10,  9,  6, 12, 11, 11, 11,  6,  9,
+    10,  9,  6, 10,  9, 12, 11,  8,  7,
+  ], [
+     6,  8,  6, 12, 11, 11, 10, 10,  9,
+     6,  1,  3, 10,  8,  8,  6,  7, 10,
+     8,  6,  3, 10,  9, 10,  8,  6,  5,
+    11, 10, 10, 12, 13, 12, 14, 13, 12,
+    10, 11,  8, 12,  9, 14, 12, 11, 12,
+     9,  9,  8, 12, 12, 10, 12, 13, 11,
+     7,  8,  6, 13,  9, 11,  7, 11, 11,
+    11, 10,  7, 14, 11, 12, 12,  7, 10,
+    12, 11,  8, 13, 12, 14, 13, 11, 10,
+  ], [
+     7, 10,  7, 13, 13, 13, 11, 11, 10,
+     8,  5,  6, 12, 11, 10,  9, 10, 11,
+     7,  5,  1,  9,  8, 10,  7,  4,  4,
+     9, 11,  9, 11, 12, 11, 13, 13, 10,
+     9, 11,  8, 13,  9, 14, 12, 11, 12,
+    11, 10, 10, 13, 12, 11, 14, 14, 12,
+     9, 10,  8, 13, 10, 14,  9, 12, 12,
+     9,  7,  4, 12, 10, 11, 10,  6,  7,
+     9,  7,  4,  9,  9, 11,  9,  7,  5,
+  ], [
+     7,  9,  7, 14, 11, 12, 10,  9,  9,
+     8,  5,  5, 12,  9, 10,  8,  8, 11,
+     7,  5,  2,  8,  8,  9,  7,  4,  4,
+    10, 11, 10, 12, 14, 11, 12, 13, 12,
+     9, 10,  8, 13,  8, 13, 10, 11, 11,
+     9,  9,  8, 14, 10, 10, 11, 12, 11,
+    10, 11,  9, 14, 10, 14,  9, 12, 14,
+     6,  6,  3, 11,  8,  9,  8,  3,  6,
+     9,  7,  4, 10,  8, 11, 10,  6,  5,
+  ], [
+     6,  8,  7, 13, 12, 12, 10,  9,  9,
+     9,  7,  8, 13, 11, 11,  9, 11, 12,
+     7,  6,  1,  9,  8, 10,  7,  5,  4,
+    10, 12, 10, 12, 13, 13, 14, 13, 11,
+     9, 11,  9, 13, 10, 14, 12, 12, 12,
+    11, 12, 10, 14, 13, 12, 13, 14, 12,
+     8,  9,  7, 13, 10, 13,  8, 11, 12,
+     8,  6,  3, 12,  9, 10,  9,  4,  6,
+    10,  8,  5, 10, 10, 12, 11,  8,  6,
+  ], [
+     7, 10,  7, 12,  9, 12, 10, 10, 12,
+     9,  7,  7, 12,  9, 11,  6, 10, 11,
+     6,  6,  1,  9,  8,  9,  7,  4,  5,
+    11, 12,  9, 12, 10, 14, 13, 13, 11,
+    10, 12,  8, 13,  8, 14, 10, 10, 11,
+    11, 11, 10, 13, 14, 10, 14, 13, 11,
+    11, 10,  7, 13,  8, 12,  7, 10, 12,
+     7, 10,  4, 12,  6, 10,  8,  5,  8,
+    10,  7,  4,  9,  7, 10,  9,  6,  5,
+  ], [
+     7,  9,  7, 13, 12, 13, 10, 10,  8,
+     8,  5,  6, 11, 10, 10,  8, 10, 10,
+     7,  5,  2,  9,  8,  9,  7,  5,  3,
+     8,  9,  7,  9, 11, 11, 13, 11,  9,
+     8, 10,  7, 12,  9, 14, 11, 10, 10,
+     9, 10,  9, 12, 12, 12, 13, 14, 12,
+    10, 10,  9, 13, 11, 13,  9, 13, 12,
+     8,  7,  4, 12, 10, 10, 10,  6,  6,
+     7,  6,  3,  9,  8, 10,  9,  6,  3,
+  ], [
+     7, 10,  7, 13, 13, 13, 11, 11,  9,
+     8,  6,  6, 13, 11, 11,  9, 10, 11,
+     7,  6,  1,  9,  8, 10,  8,  5,  4,
+     8,  9,  8,  9, 12, 12, 12, 12,  8,
+    10, 13,  9, 14, 11, 14, 14, 13, 12,
+     9, 10,  9, 13, 12, 11, 13, 14, 11,
+     9, 11,  8, 13, 11, 13, 10, 13, 13,
+     9,  8,  5, 12, 10, 11, 11,  6,  7,
+     8,  7,  3,  8,  9, 11, 10,  7,  4,
+  ], [
+     8,  9,  7, 11, 11, 12, 11, 14,  9,
+     8,  6,  6, 11, 13, 10,  9, 11,  9,
+     7,  5,  1,  7,  9,  9,  7,  5,  3,
+    13, 11,  9, 10, 12, 11, 12, 12,  9,
+    10, 11,  9, 13,  9, 12, 12, 12, 10,
+    12, 11, 10, 13, 14, 12, 14, 14, 11,
+    11,  8,  8, 13, 11, 12,  9, 13, 11,
+     9, 10,  5, 11,  8, 11,  9,  6,  7,
+     7,  8,  4,  6,  8, 10,  8,  8,  5,
+  ], [
+     8, 10,  8, 13, 13, 13, 12, 11, 10,
+     5,  1,  3, 10,  7,  8,  6,  8,  9,
+     8,  7,  4,  9, 10, 11,  8,  7,  6,
+     8,  9,  7,  9, 12, 11, 12, 10,  8,
+     9, 10,  8, 13,  9,  9, 12, 11, 11,
+     7,  7,  6, 12,  9,  8, 10, 12,  8,
+     6,  7,  4, 12,  8, 13,  6,  9, 10,
+    13, 13,  9, 15, 14, 14, 15,  9, 11,
+    13, 11,  9, 13, 13, 15, 15, 12, 10,
+  ], [
+    10,  8,  9, 11, 12, 10,  8, 13, 13,
+     9,  2,  5,  7,  5,  4,  3,  8,  9,
+    11,  5,  5,  9,  8,  8,  6,  8,  8,
+    12,  7,  8, 10, 10,  9,  8, 12, 10,
+     9, 10,  9, 12,  7, 11,  7, 12, 12,
+     9,  5,  8,  9,  9,  6,  6, 11, 10,
+     6,  4,  7,  9,  5,  9,  3,  9, 10,
+    13, 11,  9, 13, 10, 13, 10,  9, 13,
+    14, 11, 10, 12, 12, 13, 11, 14, 11,
+  ], [
+    11,  7,  8, 10, 12,  9,  9, 14, 10,
+     9,  4,  7,  8, 10,  7,  7, 11, 10,
+     8,  2,  2,  6,  8,  5,  5,  5,  6,
+    15,  9, 10, 10, 12, 10, 11, 14, 12,
+     9,  8,  9, 12,  9, 11,  8, 12, 11,
+    14, 10, 11, 12, 13, 10, 12, 15, 12,
+     9,  7,  8, 12,  9, 12,  7, 11, 13,
+     9,  6,  5, 11, 10, 11,  7,  6,  9,
+    11,  4,  5,  7,  8,  8,  8,  7,  7,
+  ]
+];
+
+const RV40_PTYPE_CODES: &[[u8; 8]; 7] = &[
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x0D, 0x05, 0x01, 0x04, 0x01, 0x00, 0x07, 0x0C ],
+  [ 0x09, 0x11, 0x01, 0x00, 0x05, 0x03, 0x21, 0x20 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ]
+];
+const RV40_PTYPE_BITS: &[[u8; 8]; 7] = &[
+  [ 1, 2, 3, 6, 5, 4, 7, 7 ],
+  [ 3, 1, 2, 7, 6, 5, 4, 7 ],
+  [ 5, 4, 1, 4, 3, 3, 4, 5 ],
+  [ 4, 5, 2, 2, 3, 2, 6, 6 ],
+  [ 5, 6, 1, 4, 2, 3, 7, 7 ],
+  [ 5, 6, 1, 4, 3, 2, 7, 7 ],
+  [ 6, 3, 2, 7, 5, 4, 1, 7 ]
+];
+const RV40_PTYPE_SYMS: &[MBType; 8] = &[
+    MBType::MBIntra,
+    MBType::MBIntra16,
+    MBType::MBP16x16,
+    MBType::MBP8x8,
+    MBType::MBP16x8,
+    MBType::MBP8x16,
+    MBType::MBP16x16Mix,
+    MBType::Invalid,
+];
+
+const RV40_BTYPE_CODES: &[[u8; 7]; 6] = &[
+  [ 0x01, 0x05, 0x00, 0x03, 0x11, 0x09, 0x10 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x09, 0x01, 0x00, 0x01, 0x05, 0x03, 0x08 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ],
+  [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 ]
+];
+const RV40_BTYPE_BITS: &[[u8; 7]; 6] = &[
+  [ 2, 3, 2, 2, 5, 4, 5 ],
+  [ 4, 1, 3, 2, 6, 5, 6 ],
+  [ 6, 4, 1, 2, 5, 3, 6 ],
+  [ 5, 3, 3, 1, 4, 3, 5 ],
+  [ 6, 5, 3, 2, 4, 1, 6 ],
+  [ 6, 5, 3, 1, 4, 2, 6 ]
+];
+const RV40_BTYPE_SYMS: &[MBType; 7] = &[
+    MBType::MBIntra,
+    MBType::MBIntra16,
+    MBType::MBForward,
+    MBType::MBBackward,
+    MBType::MBBidir,
+    MBType::MBDirect,
+    MBType::Invalid,
+];
diff --git a/src/codecs/real/rv40dsp.rs b/src/codecs/real/rv40dsp.rs
new file mode 100644 (file)
index 0000000..f118d99
--- /dev/null
@@ -0,0 +1,875 @@
+use frame::{FrameType, NAVideoBuffer};
+use codecs::MV;
+use codecs::blockdsp::edge_emu;
+use super::rv3040::{RV34DSP, RV34MBInfo};
+
+fn clip8(a: i16) -> u8 {
+    if a < 0 { 0 }
+    else if a > 255 { 255 }
+    else { a as u8 }
+}
+
+macro_rules! el {
+    ($s: ident, $o: expr) => ( $s[$o] as i16 )
+}
+
+macro_rules! filter {
+    (01; $s: ident, $o: expr, $step: expr) => (
+            clip8(((      el!($s, $o - 2 * $step)
+                     -5 * el!($s, $o - 1 * $step)
+                    +52 * el!($s, $o - 0 * $step)
+                    +20 * el!($s, $o + 1 * $step)
+                     -5 * el!($s, $o + 2 * $step)
+                        + el!($s, $o + 3 * $step) + 32) >> 6) as i16)
+        );
+    (02; $s: ident, $o: expr, $step: expr) => (
+            clip8(((      el!($s, $o - 2 * $step)
+                     -5 * el!($s, $o - 1 * $step)
+                    +20 * el!($s, $o - 0 * $step)
+                    +20 * el!($s, $o + 1 * $step)
+                     -5 * el!($s, $o + 2 * $step)
+                        + el!($s, $o + 3 * $step) + 16) >> 5) as i16)
+        );
+    (03; $s: ident, $o: expr, $step: expr) => (
+            clip8(((      el!($s, $o - 2 * $step)
+                     -5 * el!($s, $o - 1 * $step)
+                    +20 * el!($s, $o - 0 * $step)
+                    +52 * el!($s, $o + 1 * $step)
+                     -5 * el!($s, $o + 2 * $step)
+                        + el!($s, $o + 3 * $step) + 32) >> 6) as i16)
+        );
+}
+
+macro_rules! mc_func {
+    (copy; $name: ident, $size: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            for _ in 0..$size {
+                let d = &mut dst[didx..][..$size];
+                let s = &src[sidx..][..$size];
+                for x in 0..$size { d[x] = s[x]; }
+                didx += dstride;
+                sidx += sstride;
+            }
+        }
+        );
+    (mc01; $name: ident, $size: expr, $ver: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let step = if $ver { sstride } else { 1 };
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = filter!(01; src, sidx + x, step);
+                }
+                sidx += sstride;
+                didx += dstride;
+            }
+        }
+        );
+    (mc02; $name: ident, $size: expr, $ver: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let step = if $ver { sstride } else { 1 };
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = filter!(02; src, sidx + x, step);
+                }
+                sidx += sstride;
+                didx += dstride;
+            }
+        }
+        );
+    (mc03; $name: ident, $size: expr, $ver: expr) => (
+        fn $name (dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let step = if $ver { sstride } else { 1 };
+            for _ in 0..$size {
+                for x in 0..$size {
+                    dst[didx + x] = filter!(03; src, sidx + x, step);
+                }
+                sidx += sstride;
+                didx += dstride;
+            }
+        }
+        );
+    (cm01; $name: ident, $size: expr, $ofilt: ident) => (
+        fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let mut buf: [u8; ($size + 5) * $size] = [0; ($size + 5) * $size];
+            let mut bidx = 0;
+            let bstride = $size;
+            sidx -= sstride * 2;
+            for _ in 0..$size+5 {
+                for x in 0..$size { buf[bidx + x] = filter!(01; src, sidx + x, 1); }
+                bidx += bstride;
+                sidx += sstride;
+            }
+            $ofilt(dst, didx, dstride, &buf, 2*bstride, $size);
+        }
+        );
+    (cm02; $name: ident, $size: expr, $ofilt: ident) => (
+        fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let mut buf: [u8; ($size + 5) * $size] = [0; ($size + 5) * $size];
+            let mut bidx = 0;
+            let bstride = $size;
+            sidx -= sstride * 2;
+            for _ in 0..$size+5 {
+                for x in 0..$size { buf[bidx + x] = filter!(02; src, sidx + x, 1); }
+                bidx += bstride;
+                sidx += sstride;
+            }
+            $ofilt(dst, didx, dstride, &buf, 2*bstride, $size);
+        }
+        );
+    (cm03; $name: ident, $size: expr, $ofilt: ident) => (
+        fn $name (dst: &mut [u8], didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize) {
+            let mut buf: [u8; ($size + 5) * $size] = [0; ($size + 5) * $size];
+            let mut bidx = 0;
+            let bstride = $size;
+            sidx -= sstride * 2;
+            for _ in 0..$size+5 {
+                for x in 0..$size { buf[bidx + x] = filter!(03; src, sidx + x, 1); }
+                bidx += bstride;
+                sidx += sstride;
+            }
+            $ofilt(dst, didx, dstride, &buf, 2*bstride, $size);
+        }
+        );
+}
+mc_func!(copy; copy_16, 16);
+mc_func!(copy; copy_8,   8);
+mc_func!(mc01; luma_mc_10_16, 16, false);
+mc_func!(mc01; luma_mc_10_8,   8, false);
+mc_func!(mc02; luma_mc_20_16, 16, false);
+mc_func!(mc02; luma_mc_20_8,   8, false);
+mc_func!(mc03; luma_mc_30_16, 16, false);
+mc_func!(mc03; luma_mc_30_8,   8, false);
+mc_func!(mc01; luma_mc_01_16, 16, true);
+mc_func!(mc01; luma_mc_01_8,   8, true);
+mc_func!(mc02; luma_mc_02_16, 16, true);
+mc_func!(mc02; luma_mc_02_8,   8, true);
+mc_func!(mc03; luma_mc_03_16, 16, true);
+mc_func!(mc03; luma_mc_03_8,   8, true);
+mc_func!(cm01; luma_mc_11_16, 16, luma_mc_01_16);
+mc_func!(cm01; luma_mc_11_8,   8, luma_mc_01_8);
+mc_func!(cm01; luma_mc_12_16, 16, luma_mc_02_16);
+mc_func!(cm01; luma_mc_12_8,   8, luma_mc_02_8);
+mc_func!(cm01; luma_mc_13_16, 16, luma_mc_03_16);
+mc_func!(cm01; luma_mc_13_8,   8, luma_mc_03_8);
+mc_func!(cm02; luma_mc_21_16, 16, luma_mc_01_16);
+mc_func!(cm02; luma_mc_21_8,   8, luma_mc_01_8);
+mc_func!(cm02; luma_mc_22_16, 16, luma_mc_02_16);
+mc_func!(cm02; luma_mc_22_8,   8, luma_mc_02_8);
+mc_func!(cm02; luma_mc_23_16, 16, luma_mc_03_16);
+mc_func!(cm02; luma_mc_23_8,   8, luma_mc_03_8);
+mc_func!(cm03; luma_mc_31_16, 16, luma_mc_01_16);
+mc_func!(cm03; luma_mc_31_8,   8, luma_mc_01_8);
+mc_func!(cm03; luma_mc_32_16, 16, luma_mc_02_16);
+mc_func!(cm03; luma_mc_32_8,   8, luma_mc_02_8);
+mc_func!(cm03; luma_mc_33_16, 16, luma_mc_03_16);
+mc_func!(cm03; luma_mc_33_8,   8, luma_mc_03_8);
+
+const RV40_CHROMA_BIAS: [[u16; 4]; 4] = [
+    [ 0, 4, 8, 4 ],
+    [ 8, 7, 8, 7 ],
+    [ 0, 8, 4, 8 ],
+    [ 8, 7, 8, 7 ]
+];
+
+fn rv40_chroma_mc(dst: &mut [u8], mut didx: usize, dstride: usize, src: &[u8], mut sidx: usize, sstride: usize, size: usize, x: usize, y: usize) {
+    if (x == 0) && (y == 0) {
+        for _ in 0..size {
+            for x in 0..size { dst[didx + x] = src[sidx + x]; }
+            didx += dstride;
+            sidx += sstride;
+        }
+        return;
+    }
+    let bias = RV40_CHROMA_BIAS[y >> 1][x >> 1];
+    if (x > 0) && (y > 0) {
+        let a = ((4 - x) * (4 - y)) as u16;
+        let b = ((    x) * (4 - y)) as u16;
+        let c = ((4 - x) * (    y)) as u16;
+        let d = ((    x) * (    y)) as u16;
+        for _ in 0..size {
+            for x in 0..size {
+                dst[didx + x] = ((a * (src[sidx + x] as u16)
+                                + b * (src[sidx + x + 1] as u16)
+                                + c * (src[sidx + x + sstride] as u16)
+                                + d * (src[sidx + x + 1 + sstride] as u16) + bias) >> 4) as u8;
+            }
+            didx += dstride;
+            sidx += sstride;
+        }
+    } else {
+        let a = ((4 - x) * (4 - y)) as u16;
+        let e = ((    x) * (4 - y) + (4 - x) * (    y)) as u16;
+        let step = if y > 0 { sstride } else { 1 };
+        for _ in 0..size {
+            for x in 0..size {
+                dst[didx + x] = ((a * (src[sidx + x] as u16)
+                                + e * (src[sidx + x + step] as u16) + bias) >> 4) as u8;
+            }
+            didx += dstride;
+            sidx += sstride;
+        }
+    }
+}
+
+pub struct RV40DSP {
+    luma_mc: [[fn (&mut [u8], usize, usize, &[u8], usize, usize); 16]; 2],
+}
+
+impl RV40DSP {
+    pub fn new() -> Self {
+        RV40DSP {
+            luma_mc: [
+                    [ copy_16,       luma_mc_10_16,  luma_mc_20_16, luma_mc_30_16, 
+                      luma_mc_01_16, luma_mc_11_16,  luma_mc_21_16, luma_mc_31_16,
+                      luma_mc_02_16, luma_mc_12_16,  luma_mc_22_16, luma_mc_32_16,
+                      luma_mc_03_16, luma_mc_13_16,  luma_mc_23_16, luma_mc_33_16 ],
+                    [ copy_8,        luma_mc_10_8,   luma_mc_20_8,  luma_mc_30_8,
+                      luma_mc_01_8,  luma_mc_11_8,   luma_mc_21_8,  luma_mc_31_8,
+                      luma_mc_02_8,  luma_mc_12_8,   luma_mc_22_8,  luma_mc_32_8,
+                      luma_mc_03_8,  luma_mc_13_8,   luma_mc_23_8,  luma_mc_33_8 ] ],
+        }
+    }
+}
+
+macro_rules! el {
+    ($src: ident, $o: expr) => ($src[$o] as i16);
+}
+
+fn clip_symm(a: i16, lim: i16) -> i16 {
+    if a < -lim {
+        -lim
+    } else if a > lim {
+        lim
+    } else {
+        a
+    }
+}
+
+fn rv40_weak_loop_filter4(pix: &mut [u8], mut off: usize, step: usize, stride: usize,
+                          filter_p1: bool, filter_q1: bool, alpha: i16, beta: i16,
+                          lim_p0q0: i16, lim_p1: i16, lim_q1: i16) {
+    for _ in 0..4 {
+        let p0 = el!(pix, off -   step);
+        let q0 = el!(pix, off);
+
+        let t = q0 - p0;
+        if t == 0 {
+            off += stride;
+            continue;
+        }
+
+        let u = (alpha * t.wrapping_abs()) >> 7;
+        if u > (if filter_p1 && filter_q1 { 2 } else { 3 }) {
+            off += stride;
+            continue;
+        }
+
+        let p2 = el!(pix, off - 3*step);
+        let p1 = el!(pix, off - 2*step);
+        let q1 = el!(pix, off +   step);
+        let q2 = el!(pix, off + 2*step);
+
+        let str;
+        if filter_p1 && filter_q1 {
+            str = (t << 2) + (p1 - q1);
+        } else {
+            str = t << 2;
+        }
+
+        let diff = clip_symm((str + 4) >> 3, lim_p0q0);
+        pix[off - step] = clip8(p0 + diff);
+        pix[off       ] = clip8(q0 - diff);
+
+        if filter_p1 && ((p1 - p0).wrapping_abs() <= beta) {
+            let p1_diff = ((p1 - p0) + (p1 - p2) - diff) >> 1;
+            pix[off - 2*step] = clip8(p1 - clip_symm(p1_diff, lim_p1));
+        }
+
+        if filter_q1 && ((q1 - q0).wrapping_abs() <= beta) {
+            let q1_diff = ((q1 - q0) + (q1 - q2) + diff) >> 1;
+            pix[off + step] = clip8(q1 - clip_symm(q1_diff, lim_q1));
+        }
+
+        off += stride;
+    }
+}
+
+fn rv40_weak_loop_filter4_h(pix: &mut [u8], off: usize, stride: usize,
+                            filter_p1: bool, filter_q1: bool, alpha: i16, beta: i16,
+                            lim_p0q0: i16, lim_p1: i16, lim_q1: i16) {
+    rv40_weak_loop_filter4(pix, off, stride, 1, filter_p1, filter_q1, alpha, beta, lim_p0q0, lim_p1, lim_q1);
+}
+fn rv40_weak_loop_filter4_v(pix: &mut [u8], off: usize, stride: usize,
+                            filter_p1: bool, filter_q1: bool, alpha: i16, beta: i16,
+                            lim_p0q0: i16, lim_p1: i16, lim_q1: i16) {
+    let src = &mut pix[off - 3..][..stride * 3 + 3 + 3];
+    for ch in src.chunks_mut(stride).take(4) {
+        assert!(ch.len() >= 3 + 3);
+        let p0 = el!(ch, 3 - 1);
+        let q0 = el!(ch, 3);
+
+        let t = q0 - p0;
+        if t == 0 {
+            continue;
+        }
+
+        let u = (alpha * t.wrapping_abs()) >> 7;
+        if u > (if filter_p1 && filter_q1 { 2 } else { 3 }) {
+            continue;
+        }
+
+        let p2 = el!(ch, 3 - 3);
+        let p1 = el!(ch, 3 - 2);
+        let q1 = el!(ch, 3 + 1);
+        let q2 = el!(ch, 3 + 2);
+
+        let str;
+        if filter_p1 && filter_q1 {
+            str = (t << 2) + (p1 - q1);
+        } else {
+            str = t << 2;
+        }
+
+        let diff = clip_symm((str + 4) >> 3, lim_p0q0);
+        ch[3 - 1] = clip8(p0 + diff);
+        ch[3    ] = clip8(q0 - diff);
+
+        if filter_p1 && ((p1 - p0).wrapping_abs() <= beta) {
+            let p1_diff = ((p1 - p0) + (p1 - p2) - diff) >> 1;
+            ch[3 - 2] = clip8(p1 - clip_symm(p1_diff, lim_p1));
+        }
+
+        if filter_q1 && ((q1 - q0).wrapping_abs() <= beta) {
+            let q1_diff = ((q1 - q0) + (q1 - q2) + diff) >> 1;
+            ch[3 + 1] = clip8(q1 - clip_symm(q1_diff, lim_q1));
+        }
+    }
+}
+
+
+const RV40_DITHER_L: [i16; 16] = [
+    0x40, 0x50, 0x20, 0x60, 0x30, 0x50, 0x40, 0x30,
+    0x50, 0x40, 0x50, 0x30, 0x60, 0x20, 0x50, 0x40
+];
+const RV40_DITHER_R: [i16; 16] = [
+    0x40, 0x30, 0x60, 0x20, 0x50, 0x30, 0x30, 0x40,
+    0x40, 0x40, 0x50, 0x30, 0x20, 0x60, 0x30, 0x40
+];
+
+fn sfilter(a: i16, b: i16, c: i16, d: i16, e: i16, dither: i16, clip: bool, lims: i16) -> i16 {
+    let val = (25 * (a + e) + 26 * (b + c + d) + dither) >> 7;
+    if clip {
+        if val < c - lims {
+            c - lims
+        } else if val > c + lims {
+            c + lims
+        } else {
+            c
+        }
+    } else {
+        val
+    }
+}
+
+fn rv40_strong_loop_filter4(pix: &mut [u8], mut off: usize, step: usize, stride: usize,
+                            alpha: i16, lims: i16, dmode: usize, chroma: bool) {
+    for i in 0..4 {
+        let p0 = el!(pix, off -   step);
+        let q0 = el!(pix, off);
+
+        let t = q0 - p0;
+        if t == 0 {
+            off += stride;
+            continue;
+        }
+
+        let fmode = (alpha * t.wrapping_abs()) >> 7;
+        if fmode > 1 {
+            off += stride;
+            continue;
+        }
+
+        let p3 = el!(pix, off - 4*step);
+        let p2 = el!(pix, off - 3*step);
+        let p1 = el!(pix, off - 2*step);
+        let q1 = el!(pix, off +   step);
+        let q2 = el!(pix, off + 2*step);
+        let q3 = el!(pix, off + 3*step);
+
+        let np0 = sfilter(p2, p1, p0, q0, q1,     RV40_DITHER_L[dmode + i], fmode != 0, lims);
+        let nq0 = sfilter(    p1, p0, q0, q1, q0, RV40_DITHER_R[dmode + i], fmode != 0, lims);
+
+        let np1 = sfilter(p3, p2, p1, np0, q0,              RV40_DITHER_L[dmode + i], fmode != 0, lims);
+        let nq1 = sfilter(             p0, nq0, q1, q2, q3, RV40_DITHER_R[dmode + i], fmode != 0, lims);
+
+        pix[off - 2*step] = np1 as u8;
+        pix[off -   step] = np0 as u8;
+        pix[off]          = nq0 as u8;
+        pix[off +   step] = nq1 as u8;
+
+        if !chroma {
+            let np2 = sfilter(np0, np1, p2, p3, np1, 64, false, 0);
+            let nq2 = sfilter(nq0, nq1, q2, q3, q2,  64, false, 0);
+            pix[off - 3*step] = np2 as u8;
+            pix[off + 2*step] = nq2 as u8;
+        }
+
+        off += stride;
+    }
+}
+
+fn rv40_loop_strength(pix: &[u8], off: usize, step: usize, stride: usize,
+                      beta: i16, beta2: i16, edge: bool) -> (bool, bool, bool) {
+    let mut sum_p1p0 = 0;
+    let mut sum_q1q0 = 0;
+
+    let mut off1 = off;
+    for _ in 0..4 {
+        sum_p1p0 += el!(pix, off1 - 2 * step) - el!(pix, off1 - step);
+        sum_q1q0 += el!(pix, off1 +     step) - el!(pix, off1);
+        off1 += stride;
+    }
+
+    let filter_p1 = sum_p1p0.wrapping_abs() < beta * 4;
+    let filter_q1 = sum_q1q0.wrapping_abs() < beta * 4;
+
+    if (!filter_p1 || !filter_q1) || !edge {
+        return (false, filter_p1, filter_q1);
+    }
+
+    let mut sum_p1p2 = 0;
+    let mut sum_q1q2 = 0;
+
+    let mut off1 = off;
+    for _ in 0..4 {
+        sum_p1p2 += el!(pix, off1 - 2 * step) - el!(pix, off1 - 3 * step);
+        sum_q1q2 += el!(pix, off1 +     step) - el!(pix, off1 + 2 * step);
+        off1 += stride;
+    }
+
+    let strong = (sum_p1p2.wrapping_abs() < beta2) && (sum_q1q2.wrapping_abs() < beta2);
+
+    (strong, filter_p1, filter_q1)
+}
+
+fn rv40_loop_strength_h(pix: &[u8], off: usize, stride: usize,
+                        beta: i16, beta2: i16, edge: bool) -> (bool, bool, bool) {
+    rv40_loop_strength(pix, off, stride, 1, beta, beta2, edge)
+}
+
+fn rv40_loop_strength_v(pix: &[u8], off: usize, stride: usize,
+                        beta: i16, beta2: i16, edge: bool) -> (bool, bool, bool) {
+    let src = &pix[off - 3..][..stride * 3 + 3 + 3];
+    let mut sum_p1p0 = 0;
+    let mut sum_q1q0 = 0;
+
+    for ch in src.chunks(stride).take(4) {
+        assert!(ch.len() >= 3 + 3);
+        sum_p1p0 += el!(ch, 3 - 2) - el!(ch, 3 - 1);
+        sum_q1q0 += el!(ch, 3 + 1) - el!(ch, 3);
+    }
+
+    let filter_p1 = sum_p1p0.wrapping_abs() < beta * 4;
+    let filter_q1 = sum_q1q0.wrapping_abs() < beta * 4;
+
+    if (!filter_p1 || !filter_q1) || !edge {
+        return (false, filter_p1, filter_q1);
+    }
+
+    let mut sum_p1p2 = 0;
+    let mut sum_q1q2 = 0;
+
+    for ch in src.chunks(stride).take(4) {
+        assert!(ch.len() >= 3 + 3);
+        sum_p1p2 += el!(ch, 3 - 2) - el!(ch, 3 - 3);
+        sum_q1q2 += el!(ch, 3 + 1) - el!(ch, 3 + 2);
+    }
+
+    let strong = (sum_p1p2.wrapping_abs() < beta2) && (sum_q1q2.wrapping_abs() < beta2);
+
+    (strong, filter_p1, filter_q1)
+}
+
+fn rv40_loop_filter4_h(pix: &mut [u8], off: usize, stride: usize,
+                     dmode: usize, lim_p1: i16, lim_q1: i16, alpha: i16, beta: i16, beta2: i16,
+                     chroma: bool, edge: bool) {
+    let (strong, filter_p1, filter_q1) = rv40_loop_strength_h(pix, off, stride, beta, beta2, edge);
+    let lims = (filter_p1 as i16) + (filter_q1 as i16) + ((lim_p1 + lim_q1) >> 1) + 1;
+
+    if strong {
+        rv40_strong_loop_filter4(pix, off, stride, 1, alpha, lims, dmode, chroma);
+    } else if filter_p1 && filter_q1 {
+        rv40_weak_loop_filter4_h(pix, off, stride, true, true, alpha, beta,
+                                 lims, lim_p1, lim_q1);
+    } else if filter_p1 || filter_q1 {
+        rv40_weak_loop_filter4_h(pix, off, stride, filter_p1, filter_q1, alpha, beta,
+                                 lims >> 1, lim_p1 >> 1, lim_q1 >> 1);
+    }
+}
+
+fn rv40_loop_filter4_v(pix: &mut [u8], off: usize, stride: usize,
+                     dmode: usize, lim_p1: i16, lim_q1: i16, alpha: i16, beta: i16, beta2: i16,
+                     chroma: bool, edge: bool) {
+    let (strong, filter_p1, filter_q1) = rv40_loop_strength_v(pix, off, stride, beta, beta2, edge);
+    let lims = (filter_p1 as i16) + (filter_q1 as i16) + ((lim_p1 + lim_q1) >> 1) + 1;
+
+    if strong {
+        rv40_strong_loop_filter4(pix, off, 1, stride, alpha, lims, dmode, chroma);
+    } else if filter_p1 && filter_q1 {
+        rv40_weak_loop_filter4_v(pix, off, stride, true, true, alpha, beta,
+                                 lims, lim_p1, lim_q1);
+    } else if filter_p1 || filter_q1 {
+        rv40_weak_loop_filter4_v(pix, off, stride, filter_p1, filter_q1, alpha, beta,
+                                 lims >> 1, lim_p1 >> 1, lim_q1 >> 1);
+    }
+}
+
+const RV40_ALPHA_TAB: [i16; 32] = [
+    128, 128, 128, 128, 128, 128, 128, 128,
+    128, 128, 122,  96,  75,  59,  47,  37,
+     29,  23,  18,  15,  13,  11,  10,   9,
+      8,   7,   6,   5,   4,   3,   2,   1
+];
+
+const RV40_BETA_TAB: [i16; 32] = [
+     0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  3,  4,  4,  4,  6,  6,
+     6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 13, 14, 15, 16, 17
+];
+
+const RV40_FILTER_CLIP_TBL: [[i16; 32]; 3] = [
+  [
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 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, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5
+  ], [
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+    1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 7, 8, 9
+  ]
+];
+
+macro_rules! test_bit {
+    ($pat: expr, $x: expr) => ( (($pat >> $x) & 1) != 0 )
+}
+
+fn check_pos(x: usize, y: usize, size: usize, w: usize, h: usize, dx: i16, dy: i16, e0: isize, e1: isize, e2: isize, e3: isize) -> bool {
+    let xn = (x as isize) + (dx as isize);
+    let yn = (y as isize) + (dy as isize);
+
+    (xn - e0 >= 0) && (xn + (size as isize) + e1 <= (w as isize)) && (yn - e2 >= 0) && (yn + (size as isize) + e3 <= (h as isize))
+}
+
+const RV40_EDGE1: [isize; 4] = [ 0, 2, 2, 2 ];
+const RV40_EDGE2: [isize; 4] = [ 0, 3, 3, 3 ];
+
+impl RV34DSP for RV40DSP {
+    fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, _ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, row: usize) {
+        // todo proper B-frame filtering?
+        let mut offs:   [usize; 3] = [0; 3];
+        let mut stride: [usize; 3] = [0; 3];
+        let (w, h) = frame.get_dimensions(0);
+        let small_frame = w * h <= 176*144;
+
+        for comp in 0..3 {
+            stride[comp] = frame.get_stride(comp);
+            let start = if comp == 0 { row * 16 } else { row * 8 };
+            offs[comp] = frame.get_offset(comp) + start * stride[comp];
+        }
+
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let mut mb_pos: usize = row * mb_w;
+        let mut left_q: usize = 0;
+        for mb_x in 0..mb_w {
+            let q = mbinfo[mb_pos].q as usize;
+            let alpha = RV40_ALPHA_TAB[q];
+            let beta  = RV40_BETA_TAB[q];
+            let beta_y = if small_frame { beta * 4 } else { beta * 3 };
+            let beta_c = beta * 3;
+
+            let cur_dbk = mbinfo[mb_pos].deblock;
+            let cur_cbp = mbinfo[mb_pos].cbp_c;
+
+            let is_strong = mbinfo[mb_pos].mbtype.is_intra_or_16();
+            let top_is_strong = is_strong || (row > 0 && mbinfo[mb_pos - mb_w].mbtype.is_intra_or_16());
+            let left_is_strong = is_strong || (mb_x > 0 && mbinfo[mb_pos - 1].mbtype.is_intra_or_16());
+
+            for y in 0..4 {
+                let yoff = offs[0] + mb_x * 16 + y * 4 * stride[0];
+                for x in 0..4 {
+                    let bpos = x + y * 4;
+                    let filter_hor_down = (y != 3) && !is_strong;
+                    let filter_ver = (x > 0) || (mb_x > 0);
+                    let filter_hor_up = (row > 0) && (x == 0) && top_is_strong;
+                    let ver_strong = (x == 0) && (mb_x > 0) && left_is_strong;
+
+                    let cur_strength: usize;
+                    if is_strong {
+                        cur_strength = 2;
+                    } else if test_bit!(cur_dbk, bpos) {
+                        cur_strength = 1;
+                    } else {
+                        cur_strength = 0;
+                    }
+
+                    let left_strength: usize;
+                    if x > 0 {
+                        if is_strong {
+                            left_strength = 2;
+                        } else if test_bit!(cur_dbk, bpos - 1) {
+                            left_strength = 1;
+                        } else {
+                            left_strength = 0;
+                        }
+                    } else if mb_x > 0 {
+                        if left_is_strong {
+                            left_strength = 2;
+                        } else if test_bit!(mbinfo[mb_pos - 1].deblock, bpos + 3) {
+                            left_strength = 1;
+                        } else {
+                            left_strength = 0;
+                        }
+                    } else {
+                        left_strength = 0;
+                    }
+
+                    let bot_strength: usize;
+                    if y < 3 {
+                        if is_strong {
+                            bot_strength = 2;
+                        } else if test_bit!(cur_dbk, bpos + 4) {
+                            bot_strength = 1;
+                        } else {
+                            bot_strength = 0;
+                        }
+                    } else {
+                        bot_strength = 0;
+                    }
+
+                    let top_strength: usize;
+                    if y > 0 {
+                        if is_strong {
+                            top_strength = 2;
+                        } else if test_bit!(cur_dbk, bpos - 4) {
+                            top_strength = 1;
+                        } else {
+                            top_strength = 0;
+                        }
+                    } else if row > 0 {
+                        if top_is_strong {
+                            top_strength = 2;
+                        } else if test_bit!(mbinfo[mb_pos - mb_w].deblock, bpos + 12) {
+                            top_strength = 1;
+                        } else {
+                            top_strength = 0;
+                        }
+                    } else {
+                        top_strength = 0;
+                    }
+
+                    let l_q = if x > 0 { q } else { left_q };
+                    let top_q = if row > 0 { mbinfo[mb_pos - mb_w].q as usize } else { 0 };
+
+                    let lim_cur     = RV40_FILTER_CLIP_TBL [cur_strength][q];
+                    let lim_top     = RV40_FILTER_CLIP_TBL [top_strength][top_q];
+                    let lim_left    = RV40_FILTER_CLIP_TBL[left_strength][l_q];
+                    let lim_bottom  = RV40_FILTER_CLIP_TBL [bot_strength][q];
+
+                    let dmode = if y > 0 { x + y * 4 } else { x * 4 };
+
+                    if filter_hor_down {
+                        rv40_loop_filter4_h(dst, yoff + 4 * stride[0] + x * 4, stride[0],
+                                            dmode, lim_cur, lim_bottom, alpha, beta, beta_y, false, false);
+                    }
+                    if filter_ver && !ver_strong {
+                        rv40_loop_filter4_v(dst, yoff + x * 4, stride[0],
+                                            dmode, lim_left, lim_cur, alpha, beta, beta_y, false, false);
+                    }
+                    if filter_hor_up {
+                        rv40_loop_filter4_h(dst, yoff + x * 4, stride[0],
+                                            dmode, lim_top, lim_cur, alpha, beta, beta_y, false, true);
+                    }
+                    if filter_ver && ver_strong {
+                        rv40_loop_filter4_v(dst, yoff + x * 4, stride[0],
+                                            dmode, lim_left, lim_cur, alpha, beta, beta_y, false, true);
+                    }
+                }
+            }
+
+            for comp in 1..3 {
+                for y in 0..2 {
+                    let coff = offs[comp] + mb_x * 8 + y * 4 * stride[comp];
+                    for x in 0..2 {
+                        let bpos = x + y * 2 + (comp - 1) * 4;
+
+                        let filter_hor_down = (y != 1) && !is_strong;
+                        let filter_ver = (x > 0) || (mb_x > 0);
+                        let filter_hor_up = (row > 0) && (x == 0) && top_is_strong;
+                        let ver_strong = (x == 0) && (mb_x > 0) && left_is_strong;
+
+                        let cur_strength: usize;
+                        if is_strong {
+                            cur_strength = 2;
+                        } else if test_bit!(cur_cbp, bpos) {
+                            cur_strength = 1;
+                        } else {
+                            cur_strength = 0;
+                        }
+
+                        let left_strength: usize;
+                        if x > 0 {
+                            if is_strong {
+                                left_strength = 2;
+                            } else if test_bit!(cur_cbp, bpos - 1) {
+                                left_strength = 1;
+                            } else {
+                                left_strength = 0;
+                            }
+                        } else if mb_x > 0 {
+                            if left_is_strong {
+                                left_strength = 2;
+                            } else if test_bit!(mbinfo[mb_pos - 1].cbp_c, bpos + 1) {
+                                left_strength = 1;
+                            } else {
+                                left_strength = 0;
+                            }
+                        } else {
+                            left_strength = 0;
+                        }
+
+                        let bot_strength: usize;
+                        if y == 0 {
+                            if is_strong {
+                                bot_strength = 2;
+                            } else if test_bit!(cur_cbp, bpos + 2) {
+                                bot_strength = 1;
+                            } else {
+                                bot_strength = 0;
+                            }
+                        } else {
+                            bot_strength = 0;
+                        }
+
+                        let top_strength: usize;
+                        if y > 0 {
+                            if is_strong {
+                                top_strength = 2;
+                            } else if test_bit!(cur_cbp, bpos - 2) {
+                                top_strength = 1;
+                            } else {
+                                top_strength = 0;
+                            }
+                        } else if row > 0 {
+                            if top_is_strong {
+                                top_strength = 2;
+                            } else if test_bit!(mbinfo[mb_pos - mb_w].cbp_c, bpos + 2) {
+                                top_strength = 1;
+                            } else {
+                                top_strength = 0;
+                            }
+                        } else {
+                            top_strength = 0;
+                        }
+
+                        let l_q = if x > 0 { q } else { left_q };
+                        let top_q = if row > 0 { mbinfo[mb_pos - mb_w].q as usize } else { 0 };
+
+                        let lim_cur     = RV40_FILTER_CLIP_TBL [cur_strength][q];
+                        let lim_top     = RV40_FILTER_CLIP_TBL [top_strength][top_q];
+                        let lim_left    = RV40_FILTER_CLIP_TBL[left_strength][l_q];
+                        let lim_bottom  = RV40_FILTER_CLIP_TBL [bot_strength][q];
+
+                        if filter_hor_down {
+                            rv40_loop_filter4_h(dst, coff + 4 * stride[comp] + x * 4, stride[comp],
+                                                x * 8, lim_cur, lim_bottom, alpha, beta, beta_c, true, false);
+                        }
+                        if filter_ver && !ver_strong {
+                            rv40_loop_filter4_v(dst, coff + x * 4, stride[comp],
+                                                y * 8, lim_left, lim_cur, alpha, beta, beta_c, true, false);
+                        }
+                        if filter_hor_up {
+                            rv40_loop_filter4_h(dst, coff + x * 4, stride[comp],
+                                                x * 8, lim_top, lim_cur, alpha, beta, beta_c, true, true);
+                        }
+                        if filter_ver && ver_strong {
+                            rv40_loop_filter4_v(dst, coff + x * 4, stride[comp],
+                                                y * 8, lim_left, lim_cur, alpha, beta, beta_c, true, true);
+                        }
+                    }
+                }
+            }
+
+            left_q = q;
+
+            mb_pos += 1;
+        }
+    }
+    fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool) {
+        let size: usize = if use16 { 16 } else { 8 };
+        let dstride = frame.get_stride(0);
+        let doffset = frame.get_offset(0) + (if !avg { x + y * dstride } else { 0 });
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let (w_, h_) = prev_frame.get_dimensions(0);
+        let w = (w_ + 15) & !15;
+        let h = (h_ + 15) & !15;
+
+        let dx = mv.x >> 2;
+        let cx = (mv.x & 3) as usize;
+        let dy = mv.y >> 2;
+        let cy = (mv.y & 3) as usize;
+        let mode = cx + cy * 4;
+
+        if check_pos(x, y, size, w, h, dx, dy, RV40_EDGE1[cx], RV40_EDGE2[cx], RV40_EDGE1[cy], RV40_EDGE2[cy]) {
+            let sstride = prev_frame.get_stride(0);
+            let mut soffset = prev_frame.get_offset(0) + x + y * sstride;
+            let data = prev_frame.get_data();
+            let src: &[u8] = data.as_slice();
+            soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize;
+            self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, src, soffset, sstride);
+        } else {
+            let mut ebuf: [u8; 32*22] = [0; 32*22];
+            edge_emu(prev_frame, (x as isize) + (dx as isize) - 2, (y as isize) + (dy as isize) - 2, 16+5, 16+5, &mut ebuf, 32, 0);
+            self.luma_mc[if use16 { 0 } else { 1 }][mode](dst, doffset, dstride, &ebuf, 32*2 + 2, 32);
+        }
+    }
+    fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool) {
+        let size: usize = if use8 { 8 } else { 4 };
+        let dstride = frame.get_stride(comp);
+        let doffset = frame.get_offset(comp) + (if !avg { x + y * dstride } else { 0 });
+        let mut data = frame.get_data_mut();
+        let dst: &mut [u8] = data.as_mut_slice();
+
+        let (w_, h_) = prev_frame.get_dimensions(comp);
+        let w = (w_ + 7) & !7;
+        let h = (h_ + 7) & !7;
+
+        let mvx = mv.x / 2;
+        let mvy = mv.y / 2;
+        let dx = mvx >> 2;
+        let mut cx = (mvx & 3) as usize;
+        let dy = mvy >> 2;
+        let mut cy = (mvy & 3) as usize;
+
+        if (cx == 3) && (cy == 3) {
+            cx = 2;
+            cy = 2;
+        }
+
+        if check_pos(x, y, size, w, h, dx, dy, 0, 1, 0, 1) {
+            let sstride = prev_frame.get_stride(comp);
+            let mut soffset = prev_frame.get_offset(comp) + x + y * sstride;
+            let data = prev_frame.get_data();
+            let src: &[u8] = data.as_slice();
+            soffset = ((soffset as isize) + (dx as isize) + (dy as isize) * (sstride as isize)) as usize;
+            rv40_chroma_mc(dst, doffset, dstride, src, soffset, sstride, size, cx, cy);
+        } else {
+            let mut ebuf: [u8; 16*10] = [0; 16*10];
+            edge_emu(prev_frame, (x as isize) + (dx as isize), (y as isize) + (dy as isize), 8+1, 8+1, &mut ebuf, 16, comp);
+            rv40_chroma_mc(dst, doffset, dstride, &ebuf, 0, 16, size, cx, cy);
+        }
+    }
+}