From 62fbd6fd1ae26c792fcf8ccacdf68a928bd4276c Mon Sep 17 00:00:00 2001 From: bendn Date: Tue, 5 Sep 2023 06:45:23 +0700 Subject: [PATCH] init --- .gitignore | 2 + Cargo.toml | 23 +++ LICENSE | 21 +++ README.md | 9 ++ rust-toolchain.toml | 2 + src/affine.rs | 255 ++++++++++++++++++++++++++++++++ src/lib.rs | 287 ++++++++++++++++++++++++++++++++++++ src/overlay.rs | 250 +++++++++++++++++++++++++++++++ test_data/3_4x4.imgbuf | 1 + test_data/4_180x180.imgbuf | Bin 0 -> 102400 bytes test_data/4_4x4.imgbuf | 1 + test_results/3x3_at_out.buf | 1 + test_results/4x3_at_out.buf | 1 + test_results/4x4_at_out.buf | 1 + 14 files changed, 854 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 rust-toolchain.toml create mode 100644 src/affine.rs create mode 100644 src/lib.rs create mode 100644 src/overlay.rs create mode 100644 test_data/3_4x4.imgbuf create mode 100644 test_data/4_180x180.imgbuf create mode 100644 test_data/4_4x4.imgbuf create mode 100644 test_results/3x3_at_out.buf create mode 100644 test_results/4x3_at_out.buf create mode 100644 test_results/4x4_at_out.buf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1c85e52 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "fimg" +version = "0.1.0" +authors = ["bend-n "] +license = "MIT" +edition = "2021" +description = "fast image operations" +repository = "https://github.com/bend-n/fimg" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +png = { version = "0.17", features = ["unstable"], optional = true } + +[features] +save = ["png"] +default = ["save"] + +[profile.release] +debug = 2 +opt-level = 3 +lto = "thin" +incremental = true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1fafc15 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 bendn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f77c5cc --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# fimg + +quick simple image operations + +## supported operations + +- [x] overlay +- [x] rotation +- [x] flipping \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/src/affine.rs b/src/affine.rs new file mode 100644 index 0000000..18f19ee --- /dev/null +++ b/src/affine.rs @@ -0,0 +1,255 @@ +use crate::{FromRefMut, Image}; + +pub trait Rotations { + /// Rotate a image 180 degrees clockwise. + fn rot_180(&mut self); + /// Rotate a image 90 degrees clockwise. + /// # Safety + /// + /// UB if the image is not square + unsafe fn rot_90(&mut self); + /// Rotate a image 270 degrees clockwise, or 90 degrees anti clockwise. + /// # Safety + /// + /// UB if the image is not square + unsafe fn rot_270(&mut self); +} + +pub trait Flips { + /// Flip a image vertically. + fn flip_v(&mut self); + + /// Flip a image horizontally. + fn flip_h(&mut self); +} + +impl Flips for Image, CHANNELS> { + fn flip_h(&mut self) { + self.as_mut().flip_h(); + } + fn flip_v(&mut self) { + self.as_mut().flip_v(); + } +} + +impl Flips for Image<&mut [u8], CHANNELS> { + fn flip_v(&mut self) { + for y in 0..self.height() / 2 { + for x in 0..self.width() { + let y2 = self.height() - y - 1; + // SAFETY: within bounds + let p2 = unsafe { self.pixel(x, y2) }; + let p = unsafe { self.pixel(x, y) }; + unsafe { self.set_pixel(x, y2, p) }; + unsafe { self.set_pixel(x, y, p2) }; + } + } + } + + fn flip_h(&mut self) { + for y in 0..self.height() { + for x in 0..self.width() / 2 { + let x2 = self.width() - x - 1; + let p2 = unsafe { self.pixel(x2, y) }; + let p = unsafe { self.pixel(x, y) }; + unsafe { self.set_pixel(x2, y, p) }; + unsafe { self.set_pixel(x, y, p2) }; + } + } + } +} + +impl Rotations for Image, CHANNELS> { + fn rot_180(&mut self) { + self.as_mut().rot_180(); + } + + unsafe fn rot_90(&mut self) { + unsafe { self.as_mut().rot_90() } + } + + unsafe fn rot_270(&mut self) { + unsafe { self.as_mut().rot_270() } + } +} + +impl Rotations for Image<&mut [u8], CHANNELS> { + fn rot_180(&mut self) { + for y in 0..self.height() / 2 { + for x in 0..self.width() { + let p = unsafe { self.pixel(x, y) }; + let x2 = self.width() - x - 1; + let y2 = self.height() - y - 1; + let p2 = unsafe { self.pixel(x2, y2) }; + unsafe { self.set_pixel(x, y, p2) }; + unsafe { self.set_pixel(x2, y2, p) }; + } + } + + if self.height() % 2 != 0 { + let middle = self.height() / 2; + + for x in 0..self.width() / 2 { + let p = unsafe { self.pixel(x, middle) }; + let x2 = self.width() - x - 1; + let p2 = unsafe { self.pixel(x2, middle) }; + unsafe { self.set_pixel(x, middle, p2) }; + unsafe { self.set_pixel(x2, middle, p) }; + } + } + } + + #[inline] + unsafe fn rot_90(&mut self) { + // This is done by first flipping + self.flip_v(); + // Then transposing the image, to save allocations. + // SAFETY: caller ensures rectangularity + unsafe { transpose(self) }; + } + + #[inline] + unsafe fn rot_270(&mut self) { + self.flip_h(); + // SAFETY: caller ensures rectangularity + unsafe { transpose(self) }; + } +} + +/// # Safety +/// +/// UB if supplied image rectangular +unsafe fn transpose(img: &mut Image<&mut [u8], CHANNELS>) { + debug_assert_eq!(img.width(), img.height()); + let size = img.width(); + for i in 0..size { + for j in i..size { + for c in 0..CHANNELS { + // SAFETY: caller gurantees rectangularity + unsafe { + img.buffer.swap_unchecked( + (i * size + j) as usize * CHANNELS + c, + (j * size + i) as usize * CHANNELS + c, + ); + }; + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::img; + + #[test] + fn rotate_90() { + let mut from = img![ + [00, 01] + [02, 10] + ]; + unsafe { from.rot_90() }; + assert_eq!( + from, + img![ + [02, 00] + [10, 01] + ] + ); + } + + #[test] + fn rotate_180() { + let mut from = img![ + [00, 01] + [02, 10] + ]; + from.rot_180(); + assert_eq!( + from, + img![ + [10, 02] + [01, 00] + ] + ); + } + + #[test] + fn rotate_270() { + let mut from = img![ + [00, 01] + [20, 10] + ]; + unsafe { from.rot_270() }; + assert_eq!( + from, + img![ + [01, 10] + [00, 20] + ] + ); + } + + #[test] + fn flip_vertical() { + let mut from = img![ + [90, 01] + [21, 42] + ]; + from.flip_v(); + assert_eq!( + from, + img![ + [21, 42] + [90, 01] + ] + ); + } + #[test] + fn flip_horizontal() { + let mut from = img![ + [90, 01] + [21, 42] + ]; + from.flip_h(); + assert_eq!( + from, + img![ + [01, 90] + [42, 21] + ] + ); + } +} + +#[cfg(test)] +mod bench { + use super::*; + extern crate test; + use crate::Image; + use test::Bencher; + + macro_rules! bench { + (fn $name: ident() { run $fn: ident() }) => { + #[bench] + fn $name(b: &mut Bencher) { + let mut img: Image<_, 4> = Image::new( + 64.try_into().unwrap(), + 64.try_into().unwrap(), + include_bytes!("../test_data/4_180x180.imgbuf").to_vec(), + ); + b.iter(|| { + for _ in 0..256 { + img.flip_h(); + } + }); + } + }; + } + + bench!(fn flip_h() { run flip_h() }); + bench!(fn flip_v() { run flip_v() }); + bench!(fn rotate_90() { run rot_90() }); + bench!(fn rotate_180() { run rot_180() }); + bench!(fn rotate_270() { run rot_270() }); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..70b91eb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,287 @@ +#![feature( + slice_swap_unchecked, + unchecked_math, + portable_simd, + array_chunks, + test +)] +#![warn( + clippy::multiple_unsafe_ops_per_block, + clippy::missing_const_for_fn, + clippy::missing_safety_doc, + unsafe_op_in_unsafe_fn, + clippy::dbg_macro, + clippy::perf +)] +#![allow(clippy::zero_prefixed_literal)] + +use std::{num::NonZeroU32, slice::SliceIndex}; + +mod affine; +mod overlay; +pub use affine::{Flips, Rotations}; +pub use overlay::{Overlay, OverlayAt}; + +pub trait RepeatNew { + type Output; + /// Repeat self till it fills a new image of size x, y + /// # Safety + /// + /// UB if self's width is not a multiple of x, or self's height is not a multiple of y + unsafe fn repeated(&self, x: u32, y: u32) -> Self::Output; +} + +macro_rules! assert_unchecked { + ($cond:expr) => {{ + if !$cond { + #[cfg(debug_assertions)] + let _ = ::core::ptr::NonNull::<()>::dangling().as_ref(); // force unsafe wrapping block + #[cfg(debug_assertions)] + panic!("assertion failed: {} returned false", stringify!($cond)); + #[cfg(not(debug_assertions))] + std::hint::unreachable_unchecked() + } + }}; +} +use assert_unchecked; + +impl RepeatNew for Image<&[u8], 3> { + type Output = Image, 3>; + unsafe fn repeated(&self, x: u32, y: u32) -> Self::Output { + let mut img = Image::alloc(x, y); // could probably optimize this a ton but eh + for x in 0..(x / self.width()) { + for y in 0..(y / self.height()) { + let a: &mut Image<&mut [u8], 3> = &mut img.as_mut(); + // SAFETY: caller upholds + unsafe { a.overlay_at(self, x * self.width(), y * self.height()) }; + } + } + img + } +} + +#[inline] +unsafe fn really_unsafe_index(x: u32, y: u32, w: u32) -> usize { + // y * w + x + let tmp = unsafe { (y as usize).unchecked_mul(w as usize) }; + unsafe { tmp.unchecked_add(x as usize) } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Image { + pub buffer: T, + pub width: NonZeroU32, + pub height: NonZeroU32, +} + +impl Default for Image<&'static [u8], CHANNELS> { + fn default() -> Self { + Self { + buffer: &[0; CHANNELS], + width: NonZeroU32::new(1).unwrap(), + height: NonZeroU32::new(1).unwrap(), + } + } +} + +impl Image { + #[inline] + pub fn height(&self) -> u32 { + self.height.into() + } + + #[inline] + pub fn width(&self) -> u32 { + self.width.into() + } + + #[inline] + pub const fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self { + Image { + buffer, + width, + height, + } + } +} + +impl Image<&[u8], CHANNELS> { + #[inline] + #[must_use] + pub const fn copy(&self) -> Self { + Self { + width: self.width, + height: self.height, + buffer: self.buffer, + } + } +} + +impl, const CHANNELS: usize> Image { + /// # Safety + /// + /// - UB if x, y is out of bounds + /// - UB if buffer is too small + #[inline] + unsafe fn slice(&self, x: u32, y: u32) -> impl SliceIndex<[u8], Output = [u8]> { + debug_assert!(x < self.width(), "x out of bounds"); + debug_assert!(y < self.height(), "y out of bounds"); + let index = unsafe { really_unsafe_index(x, y, self.width()) }; + let index = unsafe { index.unchecked_mul(CHANNELS) }; + debug_assert!(self.buffer.len() > index); + index..unsafe { index.unchecked_add(CHANNELS) } + } + + #[inline] + /// Returns a iterator over every pixel + pub fn chunked(&self) -> impl Iterator { + // SAFETY: 0 sized images illegal + unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) }; + // SAFETY: no half pixels! + unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) }; + self.buffer.array_chunks::() + } + + /// Return a pixel at (x, y). + /// # Safety + /// + /// - UB if x, y is out of bounds + /// - UB if buffer is too small + #[inline] + pub unsafe fn pixel(&self, x: u32, y: u32) -> [u8; CHANNELS] { + let idx = unsafe { self.slice(x, y) }; + let ptr = unsafe { self.buffer.get_unchecked(idx).as_ptr().cast() }; + unsafe { *ptr } + } +} + +impl, const CHANNELS: usize> Image { + /// Return a mutable reference to a pixel at (x, y). + /// # Safety + /// + /// - UB if x, y is out of bounds + /// - UB if buffer is too small + #[inline] + pub unsafe fn pixel_mut(&mut self, x: u32, y: u32) -> &mut [u8] { + let idx = unsafe { self.slice(x, y) }; + unsafe { self.buffer.get_unchecked_mut(idx) } + } + + #[inline] + /// Returns a iterator over every pixel, mutably + pub fn chunked_mut(&mut self) -> impl Iterator { + // SAFETY: 0 sized images are not allowed + unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) }; + // SAFETY: buffer cannot have half pixels + unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) }; + self.buffer.array_chunks_mut::() + } + + /// Set the pixel at x, y + /// + /// # Safety + /// + /// UB if x, y is out of bounds. + #[inline] + pub unsafe fn set_pixel(&mut self, x: u32, y: u32, px: [u8; CHANNELS]) { + // SAFETY: Caller says that x, y is in bounds + let out = unsafe { self.pixel_mut(x, y) }; + // SAFETY: px must be CHANNELS long + unsafe { std::ptr::copy_nonoverlapping(px.as_ptr(), out.as_mut_ptr(), CHANNELS) }; + } +} + +pub trait FromRef { + /// Reference the buffer + fn as_ref(&self) -> Image<&[u8], CHANNELS>; +} + +pub trait FromRefMut { + /// Reference the buffer, mutably + fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS>; +} + +impl FromRef for Image<&mut [u8], CHANNELS> { + fn as_ref(&self) -> Image<&[u8], CHANNELS> { + Image::new(self.width, self.height, self.buffer) + } +} + +impl FromRefMut for Image<&mut [u8], CHANNELS> { + fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> { + Image::new(self.width, self.height, self.buffer) + } +} + +impl FromRef for Image, CHANNELS> { + fn as_ref(&self) -> Image<&[u8], CHANNELS> { + Image::new(self.width, self.height, &self.buffer) + } +} + +impl FromRefMut for Image, CHANNELS> { + fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> { + Image::new(self.width, self.height, &mut self.buffer) + } +} + +impl Image, CHANNELS> { + /// Allocates a new image + /// + /// # Panics + /// + /// if width || height == 0 + #[must_use] + pub fn alloc(width: u32, height: u32) -> Self { + Image { + width: width.try_into().unwrap(), + height: height.try_into().unwrap(), + buffer: vec![0; CHANNELS * width as usize * height as usize], + } + } +} +macro_rules! save { + ($channels:literal == $clr:ident ($clrhuman:literal)) => { + impl Image<&[u8], $channels> { + #[cfg(feature = "save")] + #[doc = "Save this "] + #[doc = $clrhuman] + #[doc = " image."] + pub fn save(&self, f: impl AsRef) { + let p = std::fs::File::create(f).unwrap(); + let w = &mut std::io::BufWriter::new(p); + let mut enc = png::Encoder::new(w, self.width(), self.height()); + enc.set_color(png::ColorType::$clr); + enc.set_depth(png::BitDepth::Eight); + enc.set_source_gamma(png::ScaledFloat::new(1.0 / 2.2)); + enc.set_source_chromaticities(png::SourceChromaticities::new( + (0.31270, 0.32900), + (0.64000, 0.33000), + (0.30000, 0.60000), + (0.15000, 0.06000), + )); + let mut writer = enc.write_header().unwrap(); + writer.write_image_data(self.buffer).unwrap(); + } + } + }; +} + +save!(3 == Rgb("RGB")); +save!(4 == Rgba("RGBA")); +save!(2 == GrayscaleAlpha("YA")); +save!(1 == Grayscale("Y")); + +#[cfg(test)] +macro_rules! img { + [[$($v:literal),+] [$($v2:literal),+]] => {{ + let from: Image, 1> = Image::new( + 2.try_into().unwrap(), + 2.try_into().unwrap(), + vec![$($v,)+ $($v2,)+] + ); + from + }} +} +#[cfg(test)] +use img; diff --git a/src/overlay.rs b/src/overlay.rs new file mode 100644 index 0000000..c1cac44 --- /dev/null +++ b/src/overlay.rs @@ -0,0 +1,250 @@ +use super::{assert_unchecked, really_unsafe_index, Image}; +use std::simd::SimdInt; +use std::simd::SimdPartialOrd; +use std::simd::{simd_swizzle, Simd}; + +pub trait OverlayAt { + /// Overlay with => self at coordinates x, y, without blending + /// # Safety + /// + /// UB if x, y is out of bounds + unsafe fn overlay_at(&mut self, with: &W, x: u32, y: u32) -> &mut Self; +} + +pub trait Overlay { + /// Overlay with => self (does not blend) + /// # Safety + /// + /// UB if a.width != b.width || a.height != b.height + unsafe fn overlay(&mut self, with: &W) -> &mut Self; +} + +#[inline] +unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { + const LAST4: Simd = Simd::from_array([ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, + ]); + + let mut srci = 0; + let mut dsti = 0; + while dsti + 16 <= rgb.len() { + let old: Simd = Simd::from_slice(unsafe { rgb.get_unchecked(dsti..dsti + 16) }); + let new: Simd = Simd::from_slice(unsafe { rgba.get_unchecked(srci..srci + 16) }); + + let threshold = new.simd_ge(Simd::splat(128)).to_int().cast::(); + let mut mask = simd_swizzle!( + threshold, + [3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0] + ); + mask &= LAST4; + + let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]); + let blended = (new_rgb & mask) | (old & !mask); + blended.copy_to_slice(unsafe { rgb.get_unchecked_mut(dsti..dsti + 16) }); + + srci += 16; + dsti += 12; + } + + while dsti + 3 <= rgb.len() { + if unsafe { *rgba.get_unchecked(srci + 3) } >= 128 { + let src = unsafe { rgba.get_unchecked(srci..srci + 3) }; + let end = unsafe { rgb.get_unchecked_mut(dsti..dsti + 3) }; + unsafe { std::ptr::copy_nonoverlapping(src.as_ptr(), end.as_mut_ptr(), 3) }; + } + + srci += 4; + dsti += 3; + } +} + +impl Overlay> for Image<&mut [u8], 4> { + #[inline] + unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + debug_assert!(self.width() == with.width()); + debug_assert!(self.height() == with.height()); + for (i, other_pixels) in with.chunked().enumerate() { + if other_pixels[3] >= 128 { + let idx_begin = unsafe { i.unchecked_mul(4) }; + let idx_end = unsafe { idx_begin.unchecked_add(4) }; + let own_pixels = unsafe { self.buffer.get_unchecked_mut(idx_begin..idx_end) }; + unsafe { + std::ptr::copy_nonoverlapping( + other_pixels.as_ptr(), + own_pixels.as_mut_ptr(), + 4, + ); + }; + } + } + self + } +} + +impl OverlayAt> for Image<&mut [u8], 3> { + #[inline] + unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { + // SAFETY: caller upholds these + unsafe { assert_unchecked!(x + with.width() <= self.width()) }; + unsafe { assert_unchecked!(y + with.height() <= self.height()) }; + for j in 0..with.height() { + let i_x = j as usize * with.width() as usize * 4 + ..(j as usize + 1) * with.width() as usize * 4; + let o_x = ((j as usize + y as usize) * self.width() as usize + x as usize) * 3 + ..((j as usize + y as usize) * self.width() as usize + + x as usize + + with.width() as usize) + * 3; + let rgb = unsafe { self.buffer.get_unchecked_mut(o_x) }; + let rgba = unsafe { with.buffer.get_unchecked(i_x) }; + unsafe { blit(rgb, rgba) } + } + self + } +} + +impl OverlayAt> for Image<&mut [u8], 3> { + #[inline] + unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self { + macro_rules! o3x3 { + ($n:expr) => {{ + for j in 0..($n as usize) { + let i_x = j * ($n as usize) * 3..(j + 1) * ($n as usize) * 3; + let o_x = ((j + y as usize) * self.width() as usize + x as usize) * 3 + ..((j + y as usize) * self.width() as usize + x as usize + ($n as usize)) + * 3; + let a = unsafe { self.buffer.get_unchecked_mut(o_x) }; + let b = unsafe { with.buffer.get_unchecked(i_x) }; + a.copy_from_slice(b); + } + }}; + } + // let it unroll + match with.width() { + 8 => o3x3!(8), + 16 => o3x3!(16), // this branch makes 8x8 0.16 times slower; but 16x16 0.2 times faster. + _ => o3x3!(with.width()), + } + self + } +} + +impl Overlay> for Image<&mut [u8], 3> { + #[inline] + unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + debug_assert!(self.width() == with.width()); + debug_assert!(self.height() == with.height()); + for (i, chunk) in with + .buffer + .chunks_exact(with.width() as usize * 4) + .enumerate() + { + let rgb = unsafe { + self.buffer.get_unchecked_mut( + i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3, + ) + }; + unsafe { blit(rgb, chunk) }; + } + self + } +} + +impl OverlayAt> for Image<&mut [u8], 4> { + #[inline] + unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { + for j in 0..with.height() { + for i in 0..with.width() { + let index = unsafe { really_unsafe_index(i, j, with.width()) }; + let their_px = unsafe { with.buffer.get_unchecked(index * 4..index * 4 + 4) }; + if unsafe { *their_px.get_unchecked(3) } >= 128 { + let x = unsafe { i.unchecked_add(x) }; + let y = unsafe { j.unchecked_add(y) }; + let index = unsafe { really_unsafe_index(x, y, self.width()) }; + let our_px = unsafe { self.buffer.get_unchecked_mut(index * 4..index * 4 + 4) }; + our_px.copy_from_slice(their_px); + } + } + } + + self + } +} + +#[cfg(test)] +mod bench { + extern crate test; + + use test::Bencher; + + use super::*; + use crate::{FromRef, FromRefMut}; + + #[bench] + fn overlay_3on3at(bench: &mut Bencher) { + let mut v = vec![0u8; 3 * 64 * 64]; + let mut a: Image<_, 3> = Image::new( + 64.try_into().unwrap(), + 64.try_into().unwrap(), + v.as_mut_slice(), + ); + let b = Image::<&[u8], 3>::new( + 4.try_into().unwrap(), + 4.try_into().unwrap(), + *&include_bytes!("../test_data/3_4x4.imgbuf"), + ); + bench.iter(|| unsafe { + for x in 0..16 { + for y in 0..16 { + a.overlay_at(&b, x * 4, y * 4); + } + } + }); + assert_eq!( + a.as_ref().buffer, + include_bytes!("../test_results/3x3_at_out.buf") + ); + } + + #[bench] + fn overlay_4on3at(bench: &mut Bencher) { + let mut a: Image<_, 3> = Image::alloc(64, 64); + let b = Image::<&[u8], 4>::new( + 4.try_into().unwrap(), + 4.try_into().unwrap(), + *&include_bytes!("../test_data/4_4x4.imgbuf"), + ); + bench.iter(|| unsafe { + for x in 0..16 { + for y in 0..16 { + a.as_mut().overlay_at(&b, x * 4, y * 4); + } + } + }); + assert_eq!( + a.as_ref().buffer, + include_bytes!("../test_results/4x3_at_out.buf") + ); + } + + #[bench] + fn overlay_4on4at(bench: &mut Bencher) { + let mut a: Image<_, 4> = Image::alloc(64, 64); + let b = Image::<&[u8], 4>::new( + 4.try_into().unwrap(), + 4.try_into().unwrap(), + *&include_bytes!("../test_data/4_4x4.imgbuf"), + ); + bench.iter(|| unsafe { + for x in 0..16 { + for y in 0..16 { + a.as_mut().overlay_at(&b, x * 4, y * 4); + } + } + }); + assert_eq!( + a.as_ref().buffer, + include_bytes!("../test_results/4x4_at_out.buf") + ); + } +} diff --git a/test_data/3_4x4.imgbuf b/test_data/3_4x4.imgbuf new file mode 100644 index 0000000..f3a8624 --- /dev/null +++ b/test_data/3_4x4.imgbuf @@ -0,0 +1 @@ +гЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎ \ No newline at end of file diff --git a/test_data/4_180x180.imgbuf b/test_data/4_180x180.imgbuf new file mode 100644 index 0000000000000000000000000000000000000000..58aabd0de0f36d4a6bcf8fd470e5ff9e87f8eb06 GIT binary patch literal 102400 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 literal 0 HcmV?d00001 diff --git a/test_data/4_4x4.imgbuf b/test_data/4_4x4.imgbuf new file mode 100644 index 0000000..bc6cdf8 --- /dev/null +++ b/test_data/4_4x4.imgbuf @@ -0,0 +1 @@ +жлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџЎДФџЎДФџжлчџџџџџџџџџжлчџџџџџџџџџЎДФџжлчџжлчџџџџџџџџџџџџџжлчџџџџџЎДФџжлчџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџџџџџжлчџжлчџџџџџЎДФџЎДФџжлчџжлчџжлчџЎДФџжлчџџџџџЎДФџЎДФџЎДФџжлчџЎДФџЎДФџЎДФџжлчџ \ No newline at end of file diff --git a/test_results/3x3_at_out.buf b/test_results/3x3_at_out.buf new file mode 100644 index 0000000..21d0141 --- /dev/null +++ b/test_results/3x3_at_out.buf @@ -0,0 +1 @@ +гЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎїЫЄїЫЄгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎгЎ \ No newline at end of file diff --git a/test_results/4x3_at_out.buf b/test_results/4x3_at_out.buf new file mode 100644 index 0000000..d5d8851 --- /dev/null +++ b/test_results/4x3_at_out.buf @@ -0,0 +1 @@ +жлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџЎДФжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџжлчжлчџџџџџџ \ No newline at end of file diff --git a/test_results/4x4_at_out.buf b/test_results/4x4_at_out.buf new file mode 100644 index 0000000..4dedb62 --- /dev/null +++ b/test_results/4x4_at_out.buf @@ -0,0 +1 @@ +жлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџжлчџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџЎДФџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџжлчџжлчџџџџџџџџџ \ No newline at end of file