Shrink numeric types
This commit is contained in:
parent
f76be1b112
commit
4edf6831d0
@ -5,14 +5,14 @@ use crate::{constants::{MAGIC, TILE_SZ, TILE_SZ2}, protocol::{self, ProtocolWrit
|
|||||||
|
|
||||||
struct PixelTile {
|
struct PixelTile {
|
||||||
// i32: representation that supports Walsh-Hadamard
|
// i32: representation that supports Walsh-Hadamard
|
||||||
pixels: [i32; TILE_SZ2]
|
pixels: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
struct CoefTile {
|
struct CoefTile {
|
||||||
coefs: [i32; TILE_SZ2]
|
coefs: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct QuantTile {
|
struct QuantTile {
|
||||||
quants: [i32; TILE_SZ2]
|
quants: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ impl PixelTile {
|
|||||||
let src_y = y0 + y;
|
let src_y = y0 + y;
|
||||||
pixels[y * TILE_SZ + x] =
|
pixels[y * TILE_SZ + x] =
|
||||||
if src_x < width && src_y < height {
|
if src_x < width && src_y < height {
|
||||||
layer[src_y * width + src_x] as i32
|
layer[src_y * width + src_x] as i16
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
@ -112,13 +112,13 @@ impl QuantTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_zero<W: Write>(&self, writer: &mut ProtocolWriter<W>) -> ProtocolWriterResult<()> {
|
fn write_zero<W: Write>(&self, writer: &mut ProtocolWriter<W>) -> ProtocolWriterResult<()> {
|
||||||
writer.write_i32_packed(self.quants[0])?;
|
writer.write_i16_wide(self.quants[0])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_rest<W: Write>(&self, writer: &mut ProtocolWriter<W>) -> ProtocolWriterResult<()> {
|
fn write_rest<W: Write>(&self, writer: &mut ProtocolWriter<W>) -> ProtocolWriterResult<()> {
|
||||||
for i in 1..self.quants.len() {
|
for i in 1..self.quants.len() {
|
||||||
writer.write_i32_packed(self.quants[i])?;
|
writer.write_i16_packed(self.quants[i])?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,17 @@ use crate::{constants::{MAGIC, TILE_SZ, TILE_SZ2}, protocol::{ProtocolReader, Pr
|
|||||||
|
|
||||||
struct PixelTile {
|
struct PixelTile {
|
||||||
// i32: representation that supports Walsh-Hadamard
|
// i32: representation that supports Walsh-Hadamard
|
||||||
pixels: [i32; TILE_SZ2]
|
pixels: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct CoefTile {
|
struct CoefTile {
|
||||||
coefs: [i32; TILE_SZ2]
|
coefs: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct QuantTile {
|
struct QuantTile {
|
||||||
quants: [i32; TILE_SZ2]
|
quants: [i16; TILE_SZ2]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decompress<R: Read>(
|
pub fn decompress<R: Read>(
|
||||||
@ -93,11 +93,11 @@ impl PixelTile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clip(&self, x: i32) -> u8 {
|
fn clip(&self, x: i16) -> u8 {
|
||||||
if x > u8::MAX as i32 {
|
if x > u8::MAX as i16 {
|
||||||
return u8::MAX
|
return u8::MAX
|
||||||
}
|
}
|
||||||
if x < u8::MIN as i32 {
|
if x < u8::MIN as i16 {
|
||||||
return u8::MIN;
|
return u8::MIN;
|
||||||
}
|
}
|
||||||
return x as u8;
|
return x as u8;
|
||||||
@ -116,13 +116,13 @@ impl QuantTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_zero<R: Read>(&mut self, reader: &mut ProtocolReader<R>) -> ProtocolReaderResult<()> {
|
fn load_zero<R: Read>(&mut self, reader: &mut ProtocolReader<R>) -> ProtocolReaderResult<()> {
|
||||||
self.quants[0] = reader.read_i32_packed()?;
|
self.quants[0] = reader.read_i16_wide()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_rest<R: Read>(&mut self, reader: &mut ProtocolReader<R>) -> ProtocolReaderResult<()> {
|
fn load_rest<R: Read>(&mut self, reader: &mut ProtocolReader<R>) -> ProtocolReaderResult<()> {
|
||||||
for i in 1..self.quants.len() {
|
for i in 1..self.quants.len() {
|
||||||
self.quants[i] = reader.read_i32_packed()?;
|
self.quants[i] = reader.read_i16_packed()?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -61,21 +61,19 @@ impl<W: Write> ProtocolWriter<W> {
|
|||||||
self.writer.write_all(&value.to_le_bytes())?;
|
self.writer.write_all(&value.to_le_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn write_i32_packed(&mut self, value: i32) -> ProtocolWriterResult<()> {
|
pub fn write_i16_wide(&mut self, value: i16) -> ProtocolWriterResult<()> {
|
||||||
|
self.writer.write_all(&value.to_le_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn write_i16_packed(&mut self, value: i16) -> ProtocolWriterResult<()> {
|
||||||
// We reserve i8::MAX and i16::MAX as signal values that `value` is too big
|
// We reserve i8::MAX and i16::MAX as signal values that `value` is too big
|
||||||
// for each respective type
|
// for each respective type
|
||||||
if (i8::MIN as i32..i8::MAX as i32).contains(&value) {
|
if (i8::MIN as i16..i8::MAX as i16).contains(&value) {
|
||||||
self.writer.write_all(&(value as i8).to_le_bytes())?;
|
self.writer.write_all(&(value as i8).to_le_bytes())?;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
self.writer.write_all(&(i8::MAX).to_le_bytes())?;
|
self.writer.write_all(&(i8::MAX).to_le_bytes())?;
|
||||||
|
|
||||||
if (i16::MIN as i32..i16::MAX as i32).contains(&value) {
|
|
||||||
self.writer.write_all(&(value as i16).to_le_bytes())?;
|
self.writer.write_all(&(value as i16).to_le_bytes())?;
|
||||||
return Ok(())
|
|
||||||
}
|
|
||||||
self.writer.write_all(&(i16::MAX).to_le_bytes())?;
|
|
||||||
self.writer.write_all(&value.to_le_bytes())?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,21 +103,23 @@ impl<R: Read> ProtocolReader<R> {
|
|||||||
Ok(u32::from_le_bytes(u32_buf))
|
Ok(u32::from_le_bytes(u32_buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_i32_packed(&mut self) -> ProtocolReaderResult<i32> {
|
pub fn read_i16_wide(&mut self) -> ProtocolReaderResult<i16> {
|
||||||
|
let mut i16_buf = [0; 2];
|
||||||
|
self.read_exact(&mut i16_buf)?;
|
||||||
|
|
||||||
|
Ok(i16::from_le_bytes(i16_buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_i16_packed(&mut self) -> ProtocolReaderResult<i16> {
|
||||||
let mut i8_buf = [0; 1];
|
let mut i8_buf = [0; 1];
|
||||||
self.read_exact(&mut i8_buf)?;
|
self.read_exact(&mut i8_buf)?;
|
||||||
let i8_value = i8::from_le_bytes(i8_buf);
|
let i8_value = i8::from_le_bytes(i8_buf);
|
||||||
if i8_value != i8::MAX { return Ok(i8_value as i32) }
|
if i8_value != i8::MAX { return Ok(i8_value as i16) }
|
||||||
|
|
||||||
let mut i16_buf = [0; 2];
|
let mut i16_buf = [0; 2];
|
||||||
self.read_exact(&mut i16_buf)?;
|
self.read_exact(&mut i16_buf)?;
|
||||||
let i16_value = i16::from_le_bytes(i16_buf);
|
let i16_value = i16::from_le_bytes(i16_buf);
|
||||||
if i16_value != i16::MAX { return Ok(i16_value as i32) }
|
Ok(i16_value as i16)
|
||||||
|
|
||||||
let mut i32_buf = [0; 4];
|
|
||||||
self.read_exact(&mut i32_buf)?;
|
|
||||||
let i32_value = i32::from_le_bytes(i32_buf);
|
|
||||||
Ok(i32_value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrap UnexpectedEof, since that's an error for other Io clients,
|
// wrap UnexpectedEof, since that's an error for other Io clients,
|
||||||
|
@ -12,9 +12,9 @@ const ZIGZAG: [u8; TILE_SZ2] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
pub fn to_quantized(
|
pub fn to_quantized(
|
||||||
coefs: [i32; TILE_SZ2]
|
coefs: [i16; TILE_SZ2]
|
||||||
) -> [i32; TILE_SZ2] {
|
) -> [i16; TILE_SZ2] {
|
||||||
let mut quant: [i32; TILE_SZ2] = [0; TILE_SZ2];
|
let mut quant: [i16; TILE_SZ2] = [0; TILE_SZ2];
|
||||||
|
|
||||||
for cf_ix in 0..TILE_SZ2 {
|
for cf_ix in 0..TILE_SZ2 {
|
||||||
let div = divisor(cf_ix);
|
let div = divisor(cf_ix);
|
||||||
@ -35,21 +35,21 @@ pub fn to_quantized(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_quantized(
|
pub fn from_quantized(
|
||||||
quant: [i32; TILE_SZ2]
|
quant: [i16; TILE_SZ2]
|
||||||
) -> [i32; TILE_SZ2] {
|
) -> [i16; TILE_SZ2] {
|
||||||
let mut coefs: [i32; TILE_SZ2] = [0; TILE_SZ2];
|
let mut coefs: [i16; TILE_SZ2] = [0; TILE_SZ2];
|
||||||
for cf_ix in 0..TILE_SZ2 {
|
for cf_ix in 0..TILE_SZ2 {
|
||||||
let div = divisor(cf_ix);
|
let div = divisor(cf_ix);
|
||||||
coefs[cf_ix] = quant[ZIGZAG[cf_ix] as usize] * div;
|
coefs[cf_ix] = quant[ZIGZAG[cf_ix] as usize].wrapping_mul(div);
|
||||||
}
|
}
|
||||||
coefs
|
coefs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn divisor(cf_ix: usize) -> i32 {
|
pub fn divisor(cf_ix: usize) -> i16 {
|
||||||
if cf_ix == 0 { return 1; }
|
if cf_ix == 0 { return 1; }
|
||||||
let x = cf_ix % 8;
|
let x = cf_ix % 8;
|
||||||
let y = cf_ix / 8;
|
let y = cf_ix / 8;
|
||||||
let div = 32 + (x as i32 + y as i32) * 12;
|
let div = 32 + (x as i16 + y as i16) * 12;
|
||||||
if div==32 && cf_ix != 0 {
|
if div==32 && cf_ix != 0 {
|
||||||
dbg!(cf_ix, x, y, div);
|
dbg!(cf_ix, x, y, div);
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,15 @@ use crate::constants::TILE_SZ;
|
|||||||
// This is the Walsh-Hadamard transform, specialized to 8px
|
// This is the Walsh-Hadamard transform, specialized to 8px
|
||||||
// Ported from:
|
// Ported from:
|
||||||
// - https://colab.research.google.com/drive/1WjtKwUcqxWafAumFO9ET74RsckZSsw6n#scrollTo=e3r9-RBpcgwH
|
// - https://colab.research.google.com/drive/1WjtKwUcqxWafAumFO9ET74RsckZSsw6n#scrollTo=e3r9-RBpcgwH
|
||||||
pub fn encode(data: &mut [i32], zero: usize, stride: usize) {
|
pub fn encode(data: &mut [i16], zero: usize, stride: usize) {
|
||||||
transform(data, zero, stride, 0, 0, 1)
|
transform(data, zero, stride, 0, 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(data: &mut [i32], zero: usize, stride: usize) {
|
pub fn decode(data: &mut [i16], zero: usize, stride: usize) {
|
||||||
transform(data, zero, stride, 0, 0, 8)
|
transform(data, zero, stride, 0, 0, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform(data: &mut [i32], zero: usize, stride: usize, offset_in: i32, offset_out: i32, divisor: i32) {
|
fn transform(data: &mut [i16], zero: usize, stride: usize, offset_in: i16, offset_out: i16, divisor: i16) {
|
||||||
let ix = |t| zero + t * stride;
|
let ix = |t| zero + t * stride;
|
||||||
|
|
||||||
let mut row = [0; TILE_SZ];
|
let mut row = [0; TILE_SZ];
|
||||||
@ -47,13 +47,16 @@ mod tests {
|
|||||||
use crate::{constants::TILE_SZ, transform::{decode, encode}};
|
use crate::{constants::TILE_SZ, transform::{decode, encode}};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Encodable { args: [i32; TILE_SZ] }
|
struct Encodable { args: [i16; TILE_SZ] }
|
||||||
|
|
||||||
impl Arbitrary for Encodable {
|
impl Arbitrary for Encodable {
|
||||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||||
let mut args = [0; TILE_SZ];
|
let mut args = [0; TILE_SZ];
|
||||||
for i in 0..TILE_SZ {
|
for i in 0..TILE_SZ {
|
||||||
args[i] = i16::arbitrary(g) as i32;
|
args[i] = (
|
||||||
|
i8::arbitrary(g).signum() as i32 *
|
||||||
|
(i32::arbitrary(g) % 255 * 16)
|
||||||
|
) as i16;
|
||||||
}
|
}
|
||||||
return Encodable { args };
|
return Encodable { args };
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user