aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2018-06-09 19:29:31 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2018-09-01 11:28:39 +0200
commit4752773296e6f84e69045aed2d948a66a6a031a5 (patch)
tree67c32cd30e3e8f592ad0ece0845bebe8376513e6 /src
parent3c8c667d352fc7522c3f15e8280c7cce614fbadd (diff)
downloadnihav-4752773296e6f84e69045aed2d948a66a6a031a5.tar.gz
RealVideo 3 and 4 decoder
Diffstat (limited to 'src')
-rw-r--r--src/codecs/blockdsp.rs2
-rw-r--r--src/codecs/mod.rs10
-rw-r--r--src/codecs/real/mod.rs19
-rw-r--r--src/codecs/real/rv30.rs307
-rw-r--r--src/codecs/real/rv3040.rs1321
-rw-r--r--src/codecs/real/rv30dsp.rs435
-rw-r--r--src/codecs/real/rv34codes.rs4284
-rw-r--r--src/codecs/real/rv34dsp.rs564
-rw-r--r--src/codecs/real/rv40.rs1070
-rw-r--r--src/codecs/real/rv40dsp.rs875
10 files changed, 8885 insertions, 2 deletions
diff --git a/src/codecs/blockdsp.rs b/src/codecs/blockdsp.rs
index 3d39a9e..af2ea13 100644
--- a/src/codecs/blockdsp.rs
+++ b/src/codecs/blockdsp.rs
@@ -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);
diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs
index 796973c..185bb3d 100644
--- a/src/codecs/mod.rs
+++ b/src/codecs/mod.rs
@@ -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
index 0000000..546d6b6
--- /dev/null
+++ b/src/codecs/real/mod.rs
@@ -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
index 0000000..f75b769
--- /dev/null
+++ b/src/codecs/real/rv30.rs
@@ -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
index 0000000..b3ef131
--- /dev/null
+++ b/src/codecs/real/rv3040.rs
@@ -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
index 0000000..049e002
--- /dev/null
+++ b/src/codecs/real/rv30dsp.rs
@@ -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
index 0000000..a617535
--- /dev/null
+++ b/src/codecs/real/rv34codes.rs
@@ -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
index 0000000..c8c87fb
--- /dev/null
+++ b/src/codecs/real/rv34dsp.rs
@@ -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
index 0000000..a9619d4
--- /dev/null
+++ b/src/codecs/real/rv40.rs
@@ -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
index 0000000..f118d99
--- /dev/null
+++ b/src/codecs/real/rv40dsp.rs
@@ -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);
+ }
+ }
+}